﻿/*
Typps HTML Editor for ASP.NET
FULL EDITION

Copyright (c) 2009 Alessandro Zifiglio, http://www.Typps.com
EMail: alessandro@Typps.com

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
Typps.Range = function () {
    Typps.Range.initializeBase(this);
    this._contentWindow = null;
}
Typps.Range.prototype = {
	get_contentWindow: function () { return this._contentWindow; },
	set_contentWindow: function (value) { this._contentWindow = value; },
	dispose: function () {
		var doc = this._contentWindow.document;
		if (this._range)
			delete this._range;
		Sys.Application.removeComponent(this);
		Typps.Range.callBaseMethod(this, 'dispose');
	},
	initialize: function () {
		Typps.Range.callBaseMethod(this, 'initialize');
		this._isIE = (Sys.Browser.agent == Sys.Browser.InternetExplorer);
		this._isFF = (Sys.Browser.agent == Sys.Browser.Firefox);
		this._isOpera = (Sys.Browser.agent == Sys.Browser.Opera);
		this._isWebKit = (Sys.Browser.agent == Sys.Browser.WebKit);
		this._range = null;
	},
	createRange: function () {
		var iframe = this._contentWindow;
		var sel = null;
		try {
			if (iframe.getSelection) {
				sel = iframe.getSelection();
				var rangeCount = (sel == null) ? 0 : sel.rangeCount;
				/*note we don't support multiple ranges. so instead of blindly adding many
				range objects to the selection, use the setstart/setend methods of the range object
				and make a single range object because this method will return only the first
				range object regardless*/
				if (rangeCount > 0)
					this._range = sel.getRangeAt(0);
				else
					this._range = iframe.document.createRange();
			}
			else if (iframe.document.selection) {
				//setting focus is important especially when
				//there is no selection but we need to get
				//to the blinking cursor location
				iframe.document.body.focus();
				sel = iframe.document.selection;
				if (sel.type != 'Control') {
					this._range = sel.createRange();
				}
				else {
					var controlRange = sel.createRange();
					/*we support only single controlrange selections!*/
					var elem = controlRange.item(0);
					this._range = iframe.document.body.createTextRange();
					this._range.moveToElementText(elem);
				}
			}
		}
		catch (exception) { this._range = null; }
		return this._range;
	},

	getAllNodesInRange: function (range) {
		var selectedNodes = [];

		var startContainer = null;
		var endContainer = null;
		var commonAncestor = null;
		var hasSelection = false;
		var boundary = null;
		var singleStartPoint = false;
		if (range == null) return null;

		if (range.commonAncestorContainer)
			boundary = this._getRangePoints(range); //standard DOM Range object
		else
			boundary = this._getTextRangePoints(range); //TextRange object IE only

		startContainer = boundary[0];
		endContainer = boundary[1];
		commonAncestor = boundary[2];
		hasSelection = boundary[3];
		singleStartPoint = boundary[4];

		selectedNodes.push(startContainer);

		if (!singleStartPoint && (startContainer != null && endContainer != null)) {
			//if startContainer/endContainer aren't the same
			//let's collect the nodes that exist from startContainer to endContainer
			while (startContainer = this._cakeWalk(startContainer)) {
				if (startContainer.nodeType == 1 || !Typps.Utility.isEmptyTextNode(startContainer))
					selectedNodes.push(startContainer);

				if (startContainer == endContainer)
					break;
			}
		}

		var selectedItem = new Typps.SelectedItem();
		selectedItem.set_nodes(selectedNodes);
		selectedItem.set_hasSelection(hasSelection);
		selectedItem.set_commonAncestor(commonAncestor);
		selectedItem.set_cursorNode(selectedNodes[0]);

		return selectedItem;
	},

	_cakeWalk: function (node) {
		//if we got children, get the first one
		if (node.hasChildNodes())
			return node.childNodes[0];

		//retrieve every other node adjacent to the first
		var nextSibling = node.nextSibling;

		//we got the last node in this collection
		//so, back up one level and move to the next node
		//else get the next adjacent node
		if (nextSibling == null) {
			var parentNode = node.parentNode;
			do {
				if (parentNode == null)
					break;
				if (parentNode.nextSibling)
					return parentNode.nextSibling;
			} while (parentNode = parentNode.parentNode);
		}
		return nextSibling;
	},
	_getRangePoints: function (range) {
		var startOffset = range.startOffset;
		var endOffset = range.endOffset;
		var commonAncestor = range.commonAncestorContainer;
		var iframe = this._contentWindow;
		var splitText = Typps.Utility.splitText;
		var doc = this._contentWindow.document;
		var startContainer = range.startContainer.childNodes[range.startOffset] || range.startContainer;
		var endContainer = range.endContainer.childNodes[range.endOffset] || range.endContainer;

		var hasSelection = !((startContainer.nodeType == 3 && startContainer == endContainer) && startOffset == endOffset);
		var singleStartPoint = false;
		if (startContainer == endContainer && !startContainer.hasChildNodes()) {
			singleStartPoint = true;
			if (startContainer.nodeType == 3 && startOffset > 0) {
				startContainer = splitText(doc, startContainer, startOffset);
				if (!hasSelection && startContainer.parentNode != null) {
					var cursorNode = iframe.document.createTextNode('');
					startContainer.parentNode.insertBefore(cursorNode, startContainer);
					startContainer = cursorNode;
				}
				if (endOffset > startOffset)
					endContainer = splitText(doc, startContainer, (endOffset - startOffset));
			}
		}
		else {
			if (startContainer.nodeType == 3 && startOffset > 0)
				startContainer = splitText(doc, startContainer, startOffset);
			if (endContainer.nodeType == 3 && endContainer.length > endOffset)
				splitText(doc, endContainer, endOffset);
		}
		return [startContainer, endContainer, commonAncestor, hasSelection, singleStartPoint];
	},
	_getTextRangePoints: function (range) {
		var commonAncestor = range.parentElement();
		var text = '';
		var hasText = false;
		var htmlText = '';
		var splitText = Typps.Utility.splitText;
		var doc = this._contentWindow.document;
		if (range.boundingWidth > 0) {
			text = range.text;
			hasText = text.length > 0;
			htmlText = range.htmlText;
		}
		var containsHtml = htmlText.length > 0 && htmlText != text;
		var iframe = this._contentWindow;
		var startContainer = null;
		var endContainer = null;
		//allows us to reuse our old range, after collapsing the range
		var endRange = range.duplicate();

		//collapse range to beginning of selection
		range.collapse(true);
		var tokenId = Typps.Utility.getTokenId(iframe.document);

		//insert a token
		range.pasteHTML('<span id="' + tokenId + '"></span>');
		var token = iframe.document.getElementById(tokenId);

		if (!hasText) {
			startContainer = iframe.document.createTextNode('');
			Typps.Utility.insertAfter(startContainer, token);
		}
		else {
			/*sometimes token is contained inside the previous element*/
			startContainer = token.nextSibling || token.parentNode.nextSibling;
		}

		//get rid of token
		token.parentNode.removeChild(token);

		if (!containsHtml) {
			if (hasText && (startContainer.nodeType == 3 && startContainer.length > text.length)) {
				splitText(doc, startContainer, text.length);
			}
		}
		else if (hasText) {//ensure we have a selection
			//move to the end of the selection
			endRange.collapse(false);

			//insert token
			endRange.pasteHTML('<span id="' + tokenId + '"></span>');
			token = iframe.document.getElementById(tokenId);

			endContainer = token.previousSibling || token.parentNode;
			if (endContainer != null)
				endContainer = endContainer.lastChild || endContainer;

			//get rid of token
			token.parentNode.removeChild(token);
		}
		var singleStartPoint = false;
		if (startContainer == endContainer && !startContainer.hasChildNodes())
			singleStartPoint = true;
		return [startContainer, endContainer, commonAncestor, hasText, singleStartPoint];
	},
	_getOrdinal: function (elem) {
		var parent = elem.parentNode;
		if (parent == null) return 0;
		var length = parent.childNodes.length;
		for (var num1 = 0; num1 < length; num1++) {
			var node = parent.childNodes[num1];
			if (node == elem)
				return elem.nodeType == 1 ? num1 : 0;
		}
		return 0;
	},
	select: function (startContainer, endContainer) {
		this.selectAll([startContainer, endContainer]);
	},
	selectAll: function (selectedNodes) {
		if (selectedNodes == null || selectedNodes.length == 0) return;
		var range = this.createRange();
		var sel = null;
		var iframe = this._contentWindow;
		var length = selectedNodes.length;
		var startContainer = selectedNodes[0];
		var endContainer = selectedNodes[length - 1];
		var sameEndPoint = startContainer == endContainer;
		//try {
		if (this._contentWindow.getSelection) {
			sel = iframe.getSelection();
			if (sel.rangeCount > 0) sel.removeAllRanges();

			if (startContainer.nodeType == 1) {
				if (startContainer.hasChildNodes()) {
					startContainer = startContainer.firstChild;
				}
				else {
					var startDummy = iframe.document.createTextNode('');
					Typps.Utility.insertAfter(startDummy, startContainer);
					startContainer = startDummy;
					if (sameEndPoint)
						endContainer = startContainer;
				}
			}

			if (endContainer.nodeType == 1) {
				if (endContainer.hasChildNodes()) {
					endContainer = endContainer.lastChild;
					while (endContainer.nodeType == 1 && endContainer.hasChildNodes()) {
						endContainer = endContainer.lastChild;
					}
				}
				else if (!sameEndPoint) {
					var endDummy = iframe.document.createTextNode('');
					endContainer.parentNode.insertBefore(endDummy, endContainer);
					endContainer = endDummy;
				}
			}

			var startOffset = this._getOrdinal(startContainer);
			var endOffset = this._getOrdinal(endContainer);
			if (endContainer.nodeType == 3)
				endOffset += endContainer.length; //select to the last character!

			range.setStart(startContainer, startOffset);
			if (!sameEndPoint)
				range.setEnd(endContainer, endOffset);
			sel.addRange(range);

		}
		else {
			sel = iframe.document.selection;
			if (sel.type == 'None')
				range = iframe.document.body.createTextRange();

			startContainer = this._ensureSelectableNode(startContainer, true);
			endContainer = this._ensureSelectableNode(endContainer, false);


			var rangeEnd = range.duplicate();
			rangeEnd.collapse(true);
			//define the starting range
			range.collapse(true);


			if (startContainer.nodeType == 1) {
				range.moveToElementText(startContainer);
			}
			else if (!Typps.Utility.isEmptyTextNode(startContainer)) {
				if (range.text == '') {
					//it is likely there are no characters at the current
					//cursor location, so let's backup
					range.moveStart('character', -startContainer.length);
					range.collapse(true);
				}
				range.findText(startContainer.data);
			}

			if (startContainer != endContainer) {
				//set the ending range
				if (endContainer.nodeType == 1)
					rangeEnd.moveToElementText(endContainer);
				else if (!Typps.Utility.isEmptyTextNode(endContainer))
					rangeEnd.findText(endContainer.data);

				range.collapse(true);
				rangeEnd.collapse(false);
				range.setEndPoint('StartToEnd', rangeEnd);
			}
			if (range.select) {
				range.select();
			}
		}
		//        } catch(exception) {
		//            //gobble up
		//        }
	},
	_ensureSelectableNode: function (node, forward) {
		if (Typps.Utility.isElementNode(node) ||
            !Typps.Utility.isEmptyTextNode(node))
			return node;
		var sibling = null;
		do {
			sibling = forward ? node.nextSibling : node.previousSibling;
			if (!Typps.Utility.isEmptyTextNode(sibling) && !Typps.Utility.isBr(sibling)) {
				node = sibling;
				break;
			}
		}
		while (sibling);
		return node;
	},
	selectDistinctNodes: function (nodes) {
		var length = nodes.length - 1;
		var num1 = 0;
		var node = null;
		var nodeName = null;
		var parentNode = null;
		//first pass, ensure that if child and parent are
		//in the collection, then keep the child
		for (num1 = length; num1 >= 0; num1--) {
			node = nodes[num1];
			parentNode = node.parentNode;
			while (parentNode) {
				nodeName = parentNode.nodeName.toLowerCase();
				if (nodeName == 'body') break;
				if (Array.contains(nodes, parentNode)) {
					if (this._matchesNodeSiblings(nodes, parentNode))
						Array.remove(nodes, node);
					else
						Array.remove(nodes, parentNode);
					break;
				}
				parentNode = parentNode.parentNode;
			}
		}

		//remove formatting and empty textnodes 
		length = nodes.length - 1;
		for (num1 = length; num1 >= 0; num1--) {
			node = nodes[num1];
			//we use an empty node to represent cursor location when there is no selection
			//so skip that one
			if (node.nodeType == 3 && (node.data != '' && node.data.trim() == ''))
				Array.remove(nodes, node);
		}
		return nodes;
	},
	_matchesNodeSiblings: function (list, node) {
		node = node.firstChild;
		while (node) {
			if (node.nodeType == 1) {
				var match = false;
				for (var index in list) {
					var node2 = list[index];
					if (node2 == node) {
						match = true;
						break;
					}
				}
				if (!match)
					return false;
			}
			node = node.nextSibling;
		}
		return true;
	},
	insertNodeAtSelection: function (newNode, range) {
		var selectedItem = this.getAllNodesInRange(range);
		var nodes = selectedItem.get_nodes();
		var length = nodes.length;
		var cursorNode = selectedItem.get_cursorNode();

		cursorNode.parentNode.replaceChild(newNode, cursorNode);

		if (length > 1)
			selectedItem.removeNodes();

		this.selectAll([newNode]);
	},
	insertBlockLevelElement: function (newNode, range, wrapSelectedNodes) {
		/*caller must know that not all nodes can wrap their selections, 
		eg: when inserting an html table, where in the table are you going to insert the nodes
		available within the selection? instead we want to replace the selection nodes!*/
		if (wrapSelectedNodes == null) var wrapSelectedNodes = false;
		var iframe = this._contentWindow;

		if (this._isIE && Sys.Browser.version < 9) {
			/* for older versions of ie, do it the classic way,just insert a p, mshtml will evenly breakup the 
			container node at the insertion position if it's a block level element, 
			after the split replace splitter with original intention*/
			var splitter = iframe.document.createElement('p');
			var innerHTML = range.htmlText;
			if (innerHTML == '')
				innerHTML = range.text;

			var tokenId = Typps.Utility.getTokenId();
			splitter.id = tokenId;
			range.pasteHTML(splitter.outerHTML);
			splitter = iframe.document.getElementById(tokenId);
			splitter.parentNode.replaceChild(newNode, splitter);
			if (wrapSelectedNodes)
				newNode.innerHTML = innerHTML;
		}
		else {
			var selectedItem = this.getAllNodesInRange(range);
			var nodes = selectedItem.get_nodes();
			var length = nodes.length;
			var cursorNode = selectedItem.get_cursorNode();
			var hasSelection = selectedItem.get_hasSelection();
			if (cursorNode == null) return;

			cursorNode.parentNode.insertBefore(newNode, cursorNode);

			nodes = this.selectDistinctNodes(nodes);
			length = nodes.length;

			var num1 = 0;
			var node = null;
			if (wrapSelectedNodes && hasSelection) {
				for (num1 = 0; num1 < length; num1++) {
					node = nodes[num1];
					newNode.appendChild(node);
				}
			}
			else {
				selectedItem.removeNodes(this);
			}
			if (newNode.hasChildNodes) {
				if (!newNode.hasChildNodes())
					newNode.appendChild(this._contentWindow.document.createElement('br'));
			}
		}
		this.selectAll([newNode]);
	}
}
// Register the class as derived from Sys.Component.
Typps.Range.registerClass('Typps.Range', Sys.Component);

Typps.SelectedItem = function () {
    Typps.SelectedItem.initializeBase(this);
    this._hasSelection = false;
    this._nodes = [];
    this._cursorNode = null;
    this._commonAncestor = null;
}
Typps.SelectedItem.prototype = {
    get_hasSelection: function () { return this._hasSelection; }, set_hasSelection: function (value) { this._hasSelection = value; },
    get_nodes: function () { return this._nodes; }, set_nodes: function (value) { this._nodes = value; },
    get_cursorNode: function () { return this._cursorNode; }, set_cursorNode: function (value) { this._cursorNode = value; },
    get_commonAncestor: function () { return this._commonAncestor; }, set_commonAncestor: function (value) { this._commonAncestor = value; },
    removeNodes: function (context) {
        this._nodes = context.selectDistinctNodes(this._nodes);
        var length = this._nodes.length - 1;
        for (num1 = length; num1 >= 0; num1--) {
            var node = this._nodes[num1];
            if (node != this._cursorNode)
                node.parentNode.removeChild(node);
        }
    }
}
Typps.SelectedItem.registerClass('Typps.SelectedItem');

Typps.DropDownList = function (element) {
    Typps.DropDownList.initializeBase(this, [element]);
    this._listItemClassName = null;
    this._menuItemClassName = null;
    this._selectedItemClassName = null;
    this._items = null;
    this._menuItems = null;
    this._list = null;
    this._targetId = null;
    this._targetControl = null;
    this._iframeContainer = null;
    this._commandName = null;
    this._title = '';
    this._menuList = null;
    this._isToolBar = false;
    this._listItemSelectedDelegate = null;
    this._mouseDownDelegate = null;
    this._menuItemSelectedDelegate = null;
    this._closeDelegate = null;
    this._enableToolBarFloat = false;
    this._onScrollDelegate = null;
    this._onContainerScrollDelegate = null;
    this._dropDownClassName = null;
    this._headerClassName = null;
    this._closeButtonClassName = null;
    this._selectedIndex = -1;
    this._enableEffects = true;
    this._effectDuration = 250;
}
Typps.DropDownList.prototype = {
    get_targetId: function () {
        return this._targetId;
    },
    set_targetId: function (value) {
        this._targetId = value;
    },
    get_targetControl: function () {
        return (this._targetControl == null) ? $get(this._targetId) : this._targetControl;
    },
    set_targetControl: function (value) {
        this._targetControl = value;
    },
    get_commandName: function () {
        return (this._commandName == null) ? '' : this._commandName;
    },
    set_commandName: function (value) {
        this._commandName = value;
    },
    get_title: function () {
        return this._title;
    },
    set_title: function (value) {
        this._title = value;
    },
    get_enableEffects: function () {
        return this._enableEffects;
    },
    set_enableEffects: function (value) {
        this._enableEffects = value;
    },
    get_effectDuration: function () {
        return this._effectDuration;
    },
    set_effectDuration: function (value) {
        this._effectDuration = value;
    },
    get_element: function () {
        return this._element;
    },
    get_listItemClassName: function () {
        return (this._listItemClassName == null) ? this.get_id() : this._listItemClassName;
    },
    set_listItemClassName: function (value) {
        this._listItemClassName = value;
    },
    get_menuItemClassName: function () {
        return this._menuItemClassName;
    },
    set_menuItemClassName: function (value) {
        this._menuItemClassName = value;
    },
    get_selectedItemClassName: function () {
        return this._selectedItemClassName;
    },
    set_selectedItemClassName: function (value) {
        this._selectedItemClassName = value;
    },
    get_dropDownClassName: function () {
        return this._dropDownClassName;
    },
    set_dropDownClassName: function (value) {
        this._dropDownClassName = value;
    },
    get_headerClassName: function () {
        return this._headerClassName;
    },
    set_headerClassName: function (value) {
        this._headerClassName = value;
    },
    get_closeButtonClassName: function () {
        return this._closeButtonClassName;
    },
    set_closeButtonClassName: function (value) {
        this._closeButtonClassName = value;
    },
    get_enableToolBarFloat: function () {
        return this._enableToolBarFloat;
    },
    set_enableToolBarFloat: function (value) {
        this._enableToolBarFloat = value;
    },
    get_list: function () {
        return this._list;
    },
    set_list: function (value) {
        this._list = value;
    },
    get_menuList: function () {
        return this._menuList;
    },
    set_menuList: function (value) {
        this._menuList = value;
    },
    get_isToolBar: function () {
        //special prop, specific to Typps editor
        return this._isToolBar;
    },
    set_isToolBar: function (value) {
        this._isToolBar = value;
    },
    get_iframeContainer: function () {
        //special prop, specific to Typps editor
        return this._iframeContainer;
    },
    set_iframeContainer: function (value) {
        this._iframeContainer = value;
    },
    add_listItemSelected: function (handler) {
        this.get_events().addHandler('listitemselected', handler);
    },
    remove_listItemSelected: function (handler) {
        this.get_events().removeHandler('listitemselected', handler);
    },
    add_menuItemSelected: function (handler) {
        this.get_events().addHandler('menuitemselected', handler);
    },
    remove_menuItemSelected: function (handler) {
        this.get_events().removeHandler('menuitemselected', handler);
    },
    add_close: function (handler) {
        this.get_events().addHandler('close', handler);
    },
    remove_close: function (handler) {
        this.get_events().removeHandler('close', handler);
    },
    dispose: function () {
        var id = this.get_id();
        if (this._element != null) {
            var liCollection = this._element.getElementsByTagName('a');
            for (var num1 = 0; num1 < liCollection.length; num1++) {
                var a = liCollection[num1];
                Sys.UI.DomEvent.clearHandlers(a);
            }
        }
        delete this._listItemSelectedDelegate;
        delete this._menuItemSelectedDelegate;
        delete this._mouseDownDelegate;
        var closeButton = $get(id + 'closeButton');
        if (this._closeDelegate !== null && closeButton) {
            Sys.UI.DomEvent.clearHandlers(closeButton);
            delete this._closeDelegate;
        }
        if (this._onScrollDelegate) {
            Sys.UI.DomEvent.removeHandler(this._window, 'scroll', this._onScrollDelegate);
            delete this._onScrollDelegate;
        }
        if (this._onContainerScrollDelegate) {
            if (this._iframeContainer != null)
                Sys.UI.DomEvent.removeHandler(this._iframeContainer.contentWindow, 'scroll', this._onContainerScrollDelegate);
            delete this._onContainerScrollDelegate;
        }
        Sys.Application.removeComponent(this);
        if (this._element != null) {
            if (this._element.parentNode != null)
                this._element.parentNode.removeChild(this._element);
            delete this_element;
        }
        Typps.DropDownList.callBaseMethod(this, 'dispose');
    },
    initialize: function () {
        Typps.DropDownList.callBaseMethod(this, 'initialize');
        this._isIE = (Sys.Browser.agent == Sys.Browser.InternetExplorer);
        this._isFF = (Sys.Browser.agent == Sys.Browser.Firefox);
        this._isOpera = (Sys.Browser.agent == Sys.Browser.Opera);
        this._isWebKit = (Sys.Browser.agent == Sys.Browser.WebKit);
        this._layout = null;
        this._content = null;
        this._container = null;
        this._effectSlide = null;
        this._dropDownOffsetHeight = null;
        this.hide();
        this._createWindowContainer();
        this._createDropDownList();
        this._window = window;

        if (this._onScrollDelegate == null) {
            this._onScrollDelegate = Function.createDelegate(this, this._onScrollHandler);
            Sys.UI.DomEvent.addHandler(this._window, 'scroll', this._onScrollDelegate);
        }
        if (this._onContainerScrollDelegate == null) {
            this._onContainerScrollDelegate = Function.createDelegate(this, this._onContainerScrollHandler);
            if (this._iframeContainer)
                Sys.UI.DomEvent.addHandler(this._iframeContainer.contentWindow, 'scroll', this._onContainerScrollDelegate);
        }
    },
    _onContainerScrollHandler: function (args) {
        if (this._element.style.display != 'none') {
            this._element.style.display = 'none';
            if (!this._enableEffects || this._layout == null)
                this._element.style.visibility = 'hidden';
            else
                this._addHideEffect();
        }
    },
    _onScrollHandler: function (args) {
        if (!this._enableToolBarFloat) return false;
        if (this._isIE && Sys.Browser.version == 6) {
            var context = this;
            /*Introduce a small delay. Allow the container to update it's position,
            in this case the floating toolBar, after that it's cake*/
            context._window.setTimeout(function () {
                var p = Sys.UI.DomElement.getLocation(context._targetControl);
                var newPosition = Typps.Utility.scrollDistance(context._window);
                p.y = context._targetControl.offsetHeight + 2;

                context._element.style.top = (newPosition.y + p.y) + 'px';
                context._element.style.left = (p.x) + 'px';
            }, 10);
        }
    },
    _createWindowContainer: function () {
        this._container = document.createElement('div');
        var id = this.get_id();
        this._container.id = id + '_container';
        this._layout = document.createElement('table');
        this._layout.id = id + '_layout';
        var oTBody = document.createElement('tbody');
        var headerRow = document.createElement('tr');

        var caption = document.createElement('td');
        var buttonCell = document.createElement('td');

        var button = document.createElement('a');
        button.id = id + 'closeButton';
        button.href = 'javascript:void(0);';
        button.style.textDecoration = 'none';

        var oRow2 = document.createElement('tr');
        this._content = document.createElement('td');
        this._content.id = id + '_content';

        this._element.appendChild(this._container);
        this._container.appendChild(this._layout);
        this._layout.appendChild(oTBody);
        oTBody.appendChild(headerRow);
        oTBody.appendChild(oRow2);

        buttonCell.appendChild(button);
        headerRow.appendChild(caption);
        headerRow.appendChild(buttonCell);

        oRow2.appendChild(this._content);

        this._addCssClass(this._layout, this._dropDownClassName);
        this._addCssClass(headerRow, this._headerClassName);
        this._addCssClass(button, this._closeButtonClassName);
        caption.innerHTML = this.get_title();

        this._content.colSpan = 2;
        this._layout.cellSpacing = 0;
        this._layout.cellPadding = 0;

        buttonCell.style.textAlign = 'right';
        caption.style.padding = '0 5px 0 5px';

        var position = (this._enableToolBarFloat) ? 'fixed' : 'absolute';
        if (position == 'fixed' && (this._isIE && Sys.Browser.version == 6))
            position = 'absolute';
        this._element.style.position = position;
        this._element.style.zIndex = Typps.Utility.getHighestZIndex(null);

        if (this._closeDelegate === null) {
            this._closeDelegate = Function.createDelegate(this, this._closeHandler);
        }
        Sys.UI.DomEvent.addHandler(button, 'click', this._closeDelegate);
    },
    show: function () {
        this._element.style.display = '';
        this._position();
        if (!this._enableEffects)
            this._element.style.visibility = 'visible';
        else
            this._addShowEffect();
    },
    hide: function () {
        this._element.style.display = '';
        if (this._element.style.visibility == 'hidden') return;
        if (!this._enableEffects || this._layout == null)
            this._element.style.visibility = 'hidden';
        else
            this._addHideEffect();
    },
    _addShowEffect: function () {
        this._ensureSlideEffect();
    },
    _addHideEffect: function () {
        this._ensureSlideEffect();
    },
    _ensureSlideEffect: function () {
        if (this._effectSlide == null) {
            this._effectSlide = new Spry.Effect.Slide(this.get_id(), { from: '0%', to: '100%', duration: this._effectDuration, toggle: true });
            this._registerObservers(this._effectSlide, { elem: this._element, show: true });
        }
        this._effectSlide.start();
    },
    _registerObservers: function (effect, args) {
        var context = this;
        var observe = Function.createCallback(context._onObserverHandler, { context: context, elem: args.elem, show: args.show });
        effect.addObserver(observe);
    },
    _onObserverHandler: function (notificationType, eff, data, args) {
        var context = args.context;
        switch (notificationType) {
            case 'onPreEffect':
                break;
            case 'onPostEffect':
                if (!args.show) {
                    var arg = new Typps.EventArgs();
                    arg.set_commandName(context._commandName);
                    var h = context.get_events().getHandler('close');
                    if (h) h(context, arg);
                }
                break;
            case 'onCancel':
                break;
        }
    },
    _position: function () {
        var p = Sys.UI.DomElement.getLocation(this._targetControl);
        var targetOffsetHeight = this._targetControl.offsetHeight;
        var dropDownOffsetWidth = this._element.offsetWidth;
        /*when applying special effects, the original height is not maintained by adobe spry effects (problem only in webkit), so let's maintain it ourselves*/
        if (this._dropDownOffsetHeight == null || !this._enableEffects)
            this._dropDownOffsetHeight = this._element.offsetHeight;
        var dropDownOffsetHeight = this._dropDownOffsetHeight;
        var scrollDistance = Typps.Utility.scrollDistance(this._window);
        var windowBounds = Typps.Utility.windowBounds(this._window);
        if (this._iframeContainer != null) {
            //our target is embedded in another document (iframe)
            var contentWindow = this._iframeContainer.contentWindow;
            var iframeBound = Sys.UI.DomElement.getLocation(this._iframeContainer);
            p.x += iframeBound.x;
            p.y += (iframeBound.y + targetOffsetHeight);
        } else {
            if (this._isToolBar)
                targetOffsetHeight = this._targetControl.parentNode.offsetHeight;
            p.y += targetOffsetHeight;
        }

        if (!this._isWebKit) {
            if (scrollDistance.x > 0)
                p.x -= scrollDistance.x;
            if (scrollDistance.y > 0)
                p.y -= scrollDistance.y;
        }
        /*currently if there is no space horizontally, we just flip it in the opposite direction, 
        unlike vertical positioning which is intelligent and will adapt itself within an appropriate viewable area*/
        if (dropDownOffsetWidth + p.x >= windowBounds.ix)
            p.x -= dropDownOffsetWidth;
        var verticalSpaceBelowTarget = (windowBounds.iy - p.y);
        var verticalSpaceAboveTarget = p.y;
        if ((dropDownOffsetHeight > verticalSpaceBelowTarget && dropDownOffsetHeight > verticalSpaceAboveTarget) && dropDownOffsetHeight < windowBounds.iy) {
            //if we are too big to fit below or over the target, but there's space on screen
            p.y -= (dropDownOffsetHeight - verticalSpaceBelowTarget);
        }
        else if ((dropDownOffsetHeight < verticalSpaceAboveTarget && dropDownOffsetHeight > verticalSpaceBelowTarget) && dropDownOffsetHeight < windowBounds.iy) {
            //else if we are able to fit above the target element as there is no place to fit it below the target
            p.y -= (dropDownOffsetHeight + targetOffsetHeight);
        }

        p.y += scrollDistance.y;

        this._element.style.left = p.x + 'px';
        this._element.style.top = p.y + 'px';
    },
    findItem: function (param, by) {
        for (var index in this._list) {
            var dataItem = this._list[index];
            var match = dataItem.text;
            if (by == 1)//findByValue
                match = dataItem.value;
            if (param == match) {
                var listItem = this._items.childNodes[index];
                return { dataItem: dataItem, listItem: listItem, index: index };
            }
        }
        return { dataItem: null, listItem: null, index: -1 };
    },
    selectItemByIndex: function (index) {
        var item = this._items.childNodes[index];
        if (item != null) {
            this.clearSelectedIndex();
            this._selectedIndex = index;
            this._addCssClass(item, this._selectedItemClassName);
        }
        return item;
    },
    clearSelectedIndex: function () {
        var index = this._selectedIndex;
        if (index != -1) {
            var item = this._items.childNodes[index];
            if (item != null)
                this._removeCssClass(item, this._selectedItemClassName);
            this._selectedIndex = -1;
        }
    },
    _createList: function () {
        this._items = this._createListContainer();
        this._addCssClass(this._items, this._listItemClassName);
        this._items.style.listStylePosition = 'outside';
        this._items.style.overflow = 'auto';
        for (var index in this._list) {
            var dataItem = this._list[index];
            var listItem = this._buildListItem(dataItem, index, Typps.DropDownList.ListItemType.ListItem);
            this._items.appendChild(listItem);
        }
    },
    _createMenuList: function () {
        this._menuItems = this._createListContainer();
        this._addCssClass(this._menuItems, this._menuItemClassName);
        for (var index in this._menuList) {
            var dataItem = this._menuList[index];
            var listItem = this._buildListItem(dataItem, index, Typps.DropDownList.ListItemType.MenuItem);
            this._menuItems.appendChild(listItem);
        }
    },
    _createListContainer: function () {
        var container = document.createElement('ul');
        container.style.padding = 0;
        container.tabIndex = 1;
        return container;
    },
    _buildListItem: function (dataItem, index, itemType) {
        var text = dataItem.text;
        var listItem = document.createElement('li');
        var a = document.createElement('a');
        a.href = 'javascript:void(0);';
        a.style.display = 'block';
        var customElem = listItem;
        if (dataItem.tagName != null) {
            customElem = document.createElement(dataItem.tagName);
            customElem.appendChild(a);
            listItem.appendChild(customElem);
        }
        else {
            listItem.appendChild(a);
        }
        if (dataItem.iconUrl != null) {
            var img = document.createElement('img');
            img.src = dataItem.iconUrl;
            a.appendChild(img);
        }
        a.appendChild(document.createTextNode(text));
        var value = dataItem.value != null ? dataItem.value : text;
        a.setAttribute('value', value);
        a.setAttribute('itemindex', index);
        if (dataItem.attributes != null)
            this._addAttributesToItem(customElem, dataItem.attributes);
        if (dataItem.styles != null)
            this._addStylePropertiesToItem(customElem, dataItem.styles);

        if (dataItem.toolTip != null)
            listItem.toolTip = dataItem.toolTip;

        if (this._listItemSelectedDelegate === null)
            this._listItemSelectedDelegate = Function.createDelegate(this, this._listItemSelectedHandler);
        if (this._menuItemSelectedDelegate === null)
            this._menuItemSelectedDelegate = Function.createDelegate(this, this._menuItemSelectedHandler);
        if (itemType == 0)//Typps.DropDownList.ListItemType.ListItem
            Sys.UI.DomEvent.addHandler(a, 'click', this._listItemSelectedDelegate);
        else
            Sys.UI.DomEvent.addHandler(a, 'click', this._menuItemSelectedDelegate);

        if (this._mouseDownDelegate === null)
            this._mouseDownDelegate = Function.createDelegate(this, this._mouseDownHandler);
        Sys.UI.DomEvent.addHandler(a, 'mousedown', this._mouseDownDelegate);

        return listItem;
    },
    _addAttributesToItem: function (listItem, attributes) {
        for (var index in attributes) {
            var attr = attributes[index];
            listItem.setAttribute(attr.key, attr.value);
        }
        return listItem;
    },
    _addStylePropertiesToItem: function (listItem, styles) {
        for (var index in styles) {
            var style = styles[index];
            listItem.style[style.key] = style.value;
        }
        return listItem;
    },

    _createDropDownList: function () {
        var container = this._createListContainer();
        container.style.margin = 0;
        container.style.listStyleType = 'none';
        if (this._list != null) {
            this._createList();
            var listItems = document.createElement('li');
            listItems.appendChild(this._items);
            container.appendChild(listItems);
        }
        if (this._menuList != null) {
            this._createMenuList();
            var menuItems = document.createElement('li');
            menuItems.appendChild(document.createElement('hr'));
            menuItems.appendChild(this._menuItems);
            container.appendChild(menuItems);
        }
        this._content.appendChild(container);

        if (this._layout.offsetWidth != 0)
            this._element.style.width = this._layout.offsetWidth + 'px';

        if (this._items != null && this._items.childNodes.length == 0)
            this._items.style.display = 'none';

        return container;
    },
    _mouseDownHandler: function (args) {
        //maintain previous focus
        args.preventDefault();
    },
    _menuItemSelectedHandler: function (args) {
        var arg = new Typps.SelectedItemChanged();
        var text = this._parseHyperLinkInnerHTML(args.target);
        arg.set_selectedText(text);
        arg.set_commandName(this._commandName);

        var value = args.target.getAttribute('value');
        arg.set_selectedValue(value);
        arg.set_commandArgument(value);

        var index = args.target.getAttribute('itemindex');
        arg.set_index(index);

        arg.set_innerArgs(args);
        this.hide();
        var h = this.get_events().getHandler('menuitemselected');
        if (h) h(this, arg);
    },
    _listItemSelectedHandler: function (args) {
        var arg = new Typps.SelectedItemChanged();
        var text = this._parseHyperLinkInnerHTML(args.target);
        arg.set_selectedText(text);
        arg.set_commandName(this._commandName);

        var value = args.target.getAttribute('value');
        arg.set_selectedValue(value);
        arg.set_commandArgument(value);

        var index = parseInt(args.target.getAttribute('itemindex'));
        arg.set_index(index);
        if (this._selectedIndex != -1)
            this.clearSelectedIndex();
        this._selectedIndex = index;
        this.selectItemByIndex(index);

        arg.set_innerArgs(args);
        this.hide();
        var h = this.get_events().getHandler('listitemselected');
        if (h) h(this, arg);
    },
    _closeHandler: function (args) {
        var arg = new Typps.EventArgs();
        arg.set_commandName(this._commandName);
        arg.set_innerArgs(args);
        this.hide();
        if (!this._enableEffects) {
            var h = this.get_events().getHandler('close');
            if (h) h(this, arg);
        }
    },
    _parseHyperLinkInnerHTML: function (a) {
        for (var num1 = 0; num1 < a.childNodes.length; num1++) {
            var node = a.childNodes[num1];
            if (!Typps.Utility.isEmptyTextNode(node))
                return node.data;
        }
        return '';
    },
    _toggleCssClass: function (elem, className) {
        Typps.Utility.addRemoveClassName(elem, className, Typps.Perform.Toggle);
    },
    _addCssClass: function (elem, className) {
        Typps.Utility.addRemoveClassName(elem, className, Typps.Perform.Add);
    },
    _removeCssClass: function (elem, className) {
        Typps.Utility.addRemoveClassName(elem, className, Typps.Perform.Remove);
    }
}
Typps.DropDownList.registerClass('Typps.DropDownList', Sys.UI.Control);
Typps.DropDownList.ListItemType = function () { };
Typps.DropDownList.ListItemType.prototype =
{
    ListItem: 0,
    MenuItem: 1
}
Typps.DropDownList.ListItemType.registerEnum('Typps.DropDownList.ListItemType');
Typps.DropDownList.FindItemBy = function () { };
Typps.DropDownList.FindItemBy.prototype =
{
    Text: 0,
    Value: 1
}
Typps.DropDownList.FindItemBy.registerEnum('Typps.DropDownList.FindItemBy');
Typps.SelectedItemChanged = function () {
    Typps.SelectedItemChanged.initializeBase(this);
    this._selectedText = null;
    this._selectedValue = null;
    this._index = -1;
}
Typps.SelectedItemChanged.prototype = {
    get_selectedText: function () { return this._selectedText; },
    set_selectedText: function (value) { this._selectedText = value; },
    get_selectedValue: function () { return this._selectedValue; },
    set_selectedValue: function (value) { this._selectedValue = value; },
    get_index: function () { return this._index; },
    set_index: function (value) { this._index = value; }
}
Typps.SelectedItemChanged.registerClass('Typps.SelectedItemChanged', Typps.EventArgs);

/**************************enums***********************/
Typps.SelectorState = function () { };
Typps.SelectorState.prototype =
{
    None: 0,
    Hover: 1,
    Active: 2,
    Disabled: 3
}
Typps.SelectorState.registerEnum('Typps.SelectorState');
Typps.BarItemType = function () { };
Typps.BarItemType.prototype =
{
    ToolBarItem: 0,
    TabItem: 1
}
Typps.BarItemType.registerEnum('Typps.BarItemType');
Typps.ToggleState = function () { };
Typps.ToggleState.prototype =
{
    Up: 0,
    Down: 1
}
Typps.ToggleState.registerEnum('Typps.ToggleState');
Typps.Enable = function () { };
Typps.Enable.prototype =
{
    False: 0,
    True: 1
}
Typps.Enable.registerEnum('Typps.Enable');
/***********************interfaces*******/

//ICommand
Typps.ICommand = function () { }
Typps.ICommand.prototype = {
    execute: function (args) { }
}
Typps.ICommand.registerInterface('Typps.ICommand');

//IComposite
Typps.IComposite = function () { }
Typps.IComposite.prototype = {
    add: function (name) { },
    remove: function (name) { },
    item: function (name) { },
    count: function () { }
}
Typps.IComposite.registerInterface('Typps.IComposite');

//IButtonItem
Typps.IButtonItem = function () { }
Typps.IButtonItem.prototype = {
    get_name: function () { },
    set_name: function (value) { },
    get_command: function () { },
    set_command: function (value) { }
}
Typps.IButtonItem.registerInterface('Typps.IButtonItem');

Typps.Command = function (sender, action) {
    this._sender = sender;
    this._action = action;
}
Typps.Command.prototype = {
    get_sender: function () {
        return this._sender;
    },
    set_sender: function (value) {
        this._sender = value;
    },
    get_action: function () {
        return this._action;
    },
    set_action: function (value) {
        this._action = value;
    },
    execute: function (args) {
        this._action(this._sender, args);
    }
}
Typps.Command.registerClass('Typps.Command', null, Typps.ICommand);

//IToolBarSet
Typps.IToolBarSet = function () { }
Typps.IToolBarSet.prototype = {
}
Typps.IToolBarSet.registerInterface('Typps.IToolBarSet');
/*********************base classes******/
//BarBase 
Typps.BarBase = function (element) {
    Typps.BarBase.initializeBase(this, [element]);
    this._leftBorderImage = null;
    this._optionsName = '';
    this._optionsImage = null;
    this._optionsTitle = '';
    this._className = '';
    this._mode = 1;
    this._direction = 0;
    this.items = {};
}
Typps.BarBase.prototype = {
    get_leftBorderImage: function () {
        return this._leftBorderImage;
    },
    set_leftBorderImage: function (value) {
        this._leftBorderImage = value;
    },
    get_optionsName: function () {
        return this._optionsName;
    },
    set_optionsName: function (value) {
        this._optionsName = value;
    },
    get_optionsImage: function () {
        return this._optionsImage;
    },
    set_optionsImage: function (value) {
        this._optionsImage = value;
    },
    get_optionsTitle: function () {
        return this._optionsTitle;
    },
    set_optionsTitle: function (value) {
        this._optionsTitle = value;
    },
    get_className: function () {
        return this._className;
    },
    set_className: function (value) {
        this._className = value;
    },
    get_mode: function () {
        return this._mode;
    },
    set_mode: function (value) {
        this._mode = value;
    },
    get_direction: function () {
        return this._direction;
    },
    set_direction: function (value) {
        this._direction = value;
    },
    get_enableOptions: function () {
        return !Typps.Utility.isNullOrEmpty(this._optionsName);
    },
    _addCssClass: function (elem, className) {
        Typps.Utility.addRemoveClassName(elem, className, Typps.Perform.Add);
    },
    dispose: function () {
        Typps.BarBase.callBaseMethod(this, 'dispose');
    },
    initialize: function () {
        Typps.BarBase.callBaseMethod(this, 'initialize');
        this._isIE = (Sys.Browser.agent == Sys.Browser.InternetExplorer);
        var element = this.get_element();
        var leftBorderImage = this._leftBorderImage;
        var mode = this._mode; //Typps.Editor.IconsMode
        var direction = this._direction;
        var className = this._className;
        var barItemType = this._barItemType;
        if (mode == 1 && !Typps.Utility.isNullOrEmpty(leftBorderImage)) {
            var leftEdge = document.createElement('b');
            Typps.Utility.setBackGroundImage(leftEdge, leftBorderImage, 'no-repeat', 'center center');
            this._addCssClass(leftEdge, className + (barItemType == 0/*Typps.BarItemType.ToolBarItem*/ ? '-toolbarsetleftedge' : '-tableftedge'));
            Typps.Utility.setFloat(leftEdge, direction);
            element.appendChild(leftEdge);
        }
    }
}
Typps.BarBase.registerClass('Typps.BarBase', Sys.UI.Control);

Typps.BarItemBase = function (element) {
    Typps.BarItemBase.initializeBase(this, [element]);
    this._name = '';
    this._enabled = true;
    this._marginLeft = 0;
    this._mode = 1;
    this._direction = 0;
    this._index = 0;
    this._divider = false;
    this._title = '';
    this._separatorImage = null;
    this._transparentImage = null;
    this._isOptions = false;
    this._icon = null;
    this._command = null;
    this._actionDelegate = null;
    this._toolBarMouseOverDelegate = null;
    this._toolBarMouseDownDelegate = null;
    this._toolBarMouseUpDelegate = null;
    this._toolBarMouseOutDelegate = null;
    this._barItemType = null; //Typps.BarItemType.ToolBarItem/TabItem
    this._distance = 0;
    this._toggleEnabled = false;
    this._toggleState = 0; //Typps.ToggleState.Up
    this._width = 0;
    this._disabledBackColor = null;
    this._disabledTransparency = null;
    this._disabledBorderColor = null;
}
Typps.BarItemBase.prototype = {
    get_name: function () {
        return this._name;
    },
    set_name: function (value) {
        this._name = value;
    },
    get_className: function () {
        return this._className;
    },
    set_className: function (value) {
        this._className = value;
    },
    get_enabled: function () {
        return this._enabled;
    },
    set_enabled: function (value) {
        this._enabled = value;
    },
    get_marginLeft: function () {
        return this._marginLeft;
    },
    set_marginLeft: function (value) {
        this._marginLeft = value;
    },
    get_icon: function () {
        return this._icon;
    },
    set_icon: function (value) {
        this._icon = value;
    },
    get_mode: function () {
        return this._mode;
    },
    set_mode: function (value) {
        this._mode = value;
    },
    get_direction: function () {
        return this._direction;
    },
    set_direction: function (value) {
        this._direction = value;
    },
    get_index: function () {
        return this._index;
    },
    set_index: function (value) {
        this._index = value;
    },
    get_divider: function () {
        return this._divider;
    },
    set_divider: function (value) {
        this._divider = value;
    },
    get_title: function () {
        return this._title;
    },
    set_title: function (value) {
        this._title = value;
    },
    get_separatorImage: function () {
        return this._separatorImage;
    },
    set_separatorImage: function (value) {
        this._separatorImage = value;
    },
    get_transparentImage: function () {
        return this._transparentImage;
    },
    set_transparentImage: function (value) {
        this._transparentImage = value;
    },
    get_isOptions: function () {
        return this._isOptions;
    },
    set_isOptions: function (value) {
        this._isOptions = value;
    },
    get_distance: function () {
        return this._distance;
    },
    set_distance: function (value) {
        this._distance = value;
    },
    get_width: function () {
        return this._width;
    },
    set_width: function (value) {
        this._width = value;
    },
    get_command: function () {
        return this._command;
    },
    set_command: function (value) {
        var isImplemented = Typps.ICommand.isImplementedBy(value);
        if (value && !isImplemented)
            throw 'A command needs to implement the ICommand contract';
        this._command = value;
    },
    get_barItemType: function () {
        return this._barItemType;
    },
    set_barItemType: function (value) {
        this._barItemType = value;
    },
    get_disabledBackColor: function () {
        return this._disabledBackColor;
    },
    set_disabledBackColor: function (value) {
        this._disabledBackColor = value;
    },
    get_disabledTransparency: function () {
        return this._disabledTransparency;
    },
    set_disabledTransparency: function (value) {
        this._disabledTransparency = value;
    },
    get_disabledBorderColor: function () {
        return this._disabledBorderColor;
    },
    set_disabledBorderColor: function (value) {
        this._disabledBorderColor = value;
    },
    get_toggleState: function () {
        return this._toggleState;
    },
    set_toggleState: function (value) {
        this._toggleState = value;
    },
    _disposeHandlers: function () {
        var element = this.get_element();
        if (this._actionDelegate != null)
            Sys.UI.DomEvent.removeHandler(element, 'click', this._actionDelegate);
        if (this._toolBarMouseDownDelegate != null)
            Sys.UI.DomEvent.removeHandler(element, 'mousedown', this._toolBarMouseDownDelegate);
        if (this._toolBarMouseOverDelegate != null)
            Sys.UI.DomEvent.removeHandler(element, 'mouseover', this._toolBarMouseOverDelegate);
        if (this._toolBarMouseOutDelegate != null)
            Sys.UI.DomEvent.removeHandler(element, 'mouseout', this._toolBarMouseOutDelegate);
        if (this._toolBarMouseUpDelegate != null)
            Sys.UI.DomEvent.removeHandler(element, 'mouseup', this._toolBarMouseUpDelegate);
        this._actionDelegate = null;
        delete this._toolBarMouseDownDelegate;
        delete this._toolBarMouseOverDelegate;
        delete this._toolBarMouseOutDelegate;
        delete this._toolBarMouseUpDelegate;
    },
    dispose: function () {
        var element = this.get_element();
        this._disposeHandlers();
        //finally dispose
        Typps.BarItemBase.callBaseMethod(this, 'dispose');
    },
    initialize: function () {
        Typps.BarItemBase.callBaseMethod(this, 'initialize');
        this._isIE = (Sys.Browser.agent == Sys.Browser.InternetExplorer);
    },
    _addActionHandler: function () {
        var elem = this.get_element();
        if (!this._toolBarMouseDownDelegate)
            this._toolBarMouseDownDelegate = Function.createDelegate(this, this._toolBarMouseDownHandler);
        Sys.UI.DomEvent.addHandler(elem, 'mousedown', this._toolBarMouseDownDelegate);

        var command = this.get_command();
        //ICommand implementation
        if (!this._actionDelegate) {
            var sender = command.get_sender();
            if (sender == null)
                command.set_sender(this);
            this._actionDelegate = Function.createDelegate(command, command.execute);
        }
        Sys.UI.DomEvent.addHandler(elem, 'click', this._actionDelegate);

        if (!this._toolBarMouseOverDelegate)
            this._toolBarMouseOverDelegate = Function.createDelegate(this, this._toolBarMouseOverHandler);
        Sys.UI.DomEvent.addHandler(elem, 'mouseover', this._toolBarMouseOverDelegate);

        if (!this._toolBarMouseOutDelegate)
            this._toolBarMouseOutDelegate = Function.createDelegate(this, this._toolBarMouseOutHandler);
        Sys.UI.DomEvent.addHandler(elem, 'mouseout', this._toolBarMouseOutDelegate);

        if (!this._toolBarMouseUpDelegate)
            this._toolBarMouseUpDelegate = Function.createDelegate(this, this._toolBarMouseUpHandler);
        Sys.UI.DomEvent.addHandler(elem, 'mouseup', this._toolBarMouseUpDelegate);
    },
    _toolBarMouseDownHandler: function (args) {
        //keep focus in the editable area
        args.preventDefault();
    },
    _toolBarMouseOverHandler: function (args) {
        var toggleState = this._toggleState;
        if (toggleState == 1/*Typps.ToggleState.Down*/) return;
        this.press();
    },
    _toolBarMouseOutHandler: function (args) {
        var toggleState = this._toggleState;
        if (toggleState == 1/*Typps.ToggleState.Down*/) return;
        var isTab = (this._barItemType == 1/*Typps.BarItemType.TabItem*/);
        this.release();
    },
    _toolBarMouseUpHandler: function (args) {
        var toggleState = this._toggleState;
        if (toggleState == 1/*Typps.ToggleState.Down*/) return;
        var name = this._name;
        var mode = this._mode;
        if (mode == 0/*Typps.Editor.IconType.ImageSprites*/)
            this._resetImageSpriteBackground();
    },
    press: function (selectorState) {
        if (!selectorState) var selectorState = 1; /*Typps.SelectorState.Hover*/
        var isTab = (this._barItemType == 1/*Typps.BarItemType.TabItem*/);
        var mode = this._mode;
        var className = this._className;
        var elem = this.get_element();
        if (mode == 1/*Typps.Editor.IconType.Icons*/) {
            if (isTab)
                this._addCssClass(elem, className + '-tabhoverbutton');
            else
                this._addCssClass(elem, className + '-toolbarhoverbutton');
        }
        else {
            this._imageSpriteSelector(selectorState);
        }
    },
    release: function (resetState) {
        /*resetState is optional*/
        var isTab = (this._barItemType == 1/*Typps.BarItemType.TabItem*/);
        var mode = this._mode;
        var className = this._className;
        var elem = this.get_element();
        if (mode == 1/*Typps.Editor.IconType.Icons*/) {
            if (isTab)
                this._removeCssClass(elem, className + '-tabhoverbutton');
            else
                this._removeCssClass(elem, className + '-toolbarhoverbutton');
        }
        else {
            this._resetImageSpriteBackground();
        }
        if (resetState)
            this.set_toggleState(0);
    },
    active: function () {
        /*instead of toggling this simply makes the element active (selected). The button appears pushed.*/
        this.set_toggleState(1/*Typps.ToggleState.Down*/);
        this.press(2/*Typps.SelectorState.Active*/);
    },
    togglePress: function () {
        var isPressed = this._toggleState == 1; /*Typps.ToggleState.Down*/
        var toggleState = isPressed ? 0 : 1;
        this.set_toggleState(toggleState);
        if (isPressed)
            this.release();
        else
            this.press(2/*Typps.SelectorState.Active*/);
    },
    _imageSpriteSelector: function (selectorState) {
        var target = this.get_element();
        var isTab = (this._barItemType == 1/*Typps.BarItemType.TabItem*/);
        var isOptions = this.get_isOptions();
        var container = target.parentNode;
        var horizontal = 0;
        var index = this._index;
        var distance = this._distance;
        var style1 = Sys.UI.DomElement._getCurrentStyle(container);
        var style2 = Sys.UI.DomElement._getCurrentStyle(target);

        if ((index > 0 && !isTab) && !isOptions) {
            var width = 0;
            width = parseInt(style2.width);
            horizontal = isNaN(width) ? 0 : width * index;
        }
        if (!isNaN(distance))
            horizontal += distance;

        var vertical = parseInt(style2.height);
        if (isTab)
            vertical = parseInt(style1.height);

        target.style.background = style1.backgroundImage;

        if (isNaN(vertical))
            vertical = 0;

        if (selectorState == 0/*Typps.SelectorState.None*/)
            vertical = 0;
        else if (selectorState == 2/*Typps.SelectorState.Active*/)
            vertical = vertical * 2;
        else if (selectorState == 3/*Typps.SelectorState.Disabled*/)
            vertical = vertical * 3;

        target.style.backgroundRepeat = 'no-repeat';
        var pos = String.format('-{0}px -{1}px', horizontal, vertical);

        target.style.backgroundPosition = pos;
    },
    _resetImageSpriteBackground: function () {
        var target = this.get_element();
        var transparentImage = this._transparentImage;
        if (this._isIE && Sys.Browser.version == 6)
            Typps.Utility.setBackGroundImage(target, transparentImage, 'no-repeat', 'center center');
        else
            target.style.backgroundImage = '';
    },
    _setChroma: function () {
        var elem = this.get_element();
        if ((this._isIE && Sys.Browser.version == 6) && elem != null) {
            //IE6 does not understand border-color transparency.
            var style = Sys.UI.DomElement._getCurrentStyle(elem);
            if (style.borderColor != '')
                elem.style.filter += String.format('Chroma(color={0});', style.borderColor);
        }
        else {
            elem.style.borderColor = 'transparent';
        }
    },
    _fadeOutAndDisable: function () {
        var elem = this.get_element();
        var mode = this._mode;
        elem.disabled = true;
        elem.style.cursor = 'default';
        if (mode == 1/*Typps.Editor.IconType.Icons*/) {
            var backColor = this._disabledBackColor;
            var borderColor = this._disabledBorderColor;
            var transparency = this._disabledTransparency;
            elem.style.backgroundColor = backColor;
            if (borderColor != '')
                elem.style.border = String.format('1px solid {0}', borderColor);
            Typps.Utility.setTransparency(elem, transparency);
        }
        else {
            this._imageSpriteSelector(3/*Typps.SelectorState.Disabled*/);
        }
    },
    _toggleCssClass: function (elem, className) {
        Typps.Utility.addRemoveClassName(elem, className, Typps.Perform.Toggle);
    },
    _addCssClass: function (elem, className) {
        Typps.Utility.addRemoveClassName(elem, className, Typps.Perform.Add);
    },
    _removeCssClass: function (elem, className) {
        Typps.Utility.addRemoveClassName(elem, className, Typps.Perform.Remove);
    }
}
Typps.BarItemBase.registerClass('Typps.BarItemBase', Sys.UI.Control, Typps.IButtonItem);

/*****************************************implementation classes************************************/
//Typps.ToolBars
Typps.ToolBars = function () {
    this.items = [];
}
Typps.ToolBars.prototype = {
    add: function (toolBarSet, index) {
        var isImplementedBy = Typps.IToolBarSet.isImplementedBy(toolBarSet);
        if (!isImplementedBy)
            throw "Items you add to a ToolBar must be of type ToolBarSet";
        this.items[index] = toolBarSet;
    },
    remove: function (index) {
        return this.items.splice(index, 1);
    },
    item: function (index) {
        return this.items[index];
    },
    count: function () {
        return this.items.length;
    },
    getToolBarItem: function (name) {
        var items = this.items;
        for (var i in items) {
            var toolBarSet = items[i];
            var toolBarItems = toolBarSet.items;
            for (var j in toolBarItems) {
                var item = toolBarItems[j];
                if (item.get_name() == name)
                    return item;
            }
        }
        return null;
    },
    dispose: function () {
        for (var i in this.items)
            this.items[i].dispose();
    }
}
Typps.ToolBars.registerClass('Typps.ToolBars', null, Typps.IComposite);
//ToolBarSet
Typps.ToolBarSet = function (element) {
    Typps.ToolBarSet.initializeBase(this, [element]);
    this.items = {};
}
Typps.ToolBarSet.prototype = {
    add: function (item) {
        var isImplemented = Typps.IButtonItem.isImplementedBy(item);
        if (!isImplemented)
            throw "Items you add to a ToolBarSet must implement Typps.IButtonItem interface";
        var name = item.get_name();
        var node = item.get_element();
        var element = this.get_element();
        element.appendChild(node);
        item._initialize();

        this.items[name] = item;
    },
    remove: function (name) {
        delete this.items[name];
    },
    item: function (name) {
        return this.items[name];
    },
    count: function () {
        var length = 0;
        for (var i in this.items)
            length++;
        return length;
    },
    _addCssClass: function (elem, className) {
        Typps.Utility.addRemoveClassName(elem, className, Typps.Perform.Add);
    },
    dispose: function () {
        for (var i in this._items) {
            var item = this._items[i];
            item.dispose();
        }
        Typps.ToolBarSet.callBaseMethod(this, 'dispose');
    },
    initialize: function () {
        Typps.ToolBarSet.callBaseMethod(this, 'initialize');
        var element = this.get_element();
        element.style.padding = '0px';
    }
}
Typps.ToolBarSet.registerClass('Typps.ToolBarSet', Typps.BarBase, Typps.IComposite, Typps.IToolBarSet);

//Typps.ToggleManager -> manages toggling of toolbar buttons by observing currently selected element in the editor
Typps.ToggleManager = function () {
    Typps.ToggleManager.initializeBase(this);
    this._document = null;
    this._className = null;
    this.items = {};
    this._highlightNodeNames = ['a', 'img', 'td', 'div', 'p', 'li', 'dt', 'dd',
                'blockquote', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'];
    this._highlightedNodes = [];
    this._queryCommands = ['bold', 'insertorderedlist', 'insertunorderedlist', 'italic',
        'underline', 'strikethrough', 'superscript', 'subscript', 'outdent', 'indent'];
    this._tableCommands = ['cellsdesigner', 'deletetable', 'addrowbefore', 'addrowafter', 'deleterow', 'addcolumnbefore', 'addcolumnafter', 'deletecolumn'];
    this._activeNode = {};
    this._isIE = (Sys.Browser.agent == Sys.Browser.InternetExplorer);
}
Typps.ToggleManager.prototype = {
    get_document: function () {
        return this._document;
    },
    set_document: function (value) {
        this._document = value;
    },
    get_className: function () {
        return this._className;
    },
    set_className: function (value) {
        this._className = value;
    },
    get_activeNode: function (name) {
        return this._activeNode[name];
    },
    add_onAutoToggle: function (handler) {
        this.get_events().addHandler('onautotoggle', handler);
    },
    remove_onAutoToggle: function (handler) {
        this.get_events().removeHandler('onautotoggle', handler);
    },
    _ensureContract: function (item) {
        var isImplemented = Typps.IButtonItem.isImplementedBy(item);
        if (!isImplemented)
            throw 'A toogle enabled item must implement Typps.IButtonItem interface';
    },
    add: function (item) {
        this._ensureContract(item);
        var name = item.get_name();
        /*add default watch attributes/elements a BarItem is associated to by default*/
        switch (name) {
            case 'createlink':
                item.addNodeName('a');
                break;
            case 'insertimage':
                item.addNodeName('img');
                break;
            case 'inserttable':
                item.addNodeName('td');
                break;
            case 'quote':
                item.addNodeName('blockquote');
                break;
        }
        this.items[name] = item;
    },
    remove: function (name) {
        delete this.items[name];
    },
    item: function (name) {
        return this.items[name];
    },
    count: function () {
        var length = 0;
        for (var i in this.items)
            length++;
        return length;
    },
    active: function (name) {
        this.items[name].active();
    },
    _getAttributeValue: function (elem, attributeName, cssPropName) {
        var value = elem.getAttribute(attributeName);
        if (value)
            return value;
        if (cssPropName) {
            /*css property name has to be the js equivalent eg: textAlign and not text-align*/
            value = elem.style[cssPropName];
            if (!Typps.Utility.isNullOrEmpty(value))
                return value;
        }
        return null;
    },
    _enableOrDisableByRange: function (range, value/*Typps.Enable*/) {
        if (value == null) var enable = 1/*Typps.Enable.True*/;
        /*takes an array of ToolBarItem names to make active*/
        var items = this.items;
        for (var i in range) {
            var name = range[i];
            var item = items[name];
            if (item) {
                this._ensureContract(item);
                if (value == 1)
                    item.enable();
                else
                    item.disable();
            }
        }
    },
    _clearActiveNode: function () {
        for (var i in this._activeNode) 
            delete this._activeNode[i];
    },
    release: function (name) {
        this.items[name].release(true);
    },
    get_names: function () {
        var items = this.items;
        var names = [];
        for (var name in items)
            Array.add(names, name);
        return names
    },
    releaseAll: function () {
        var items = this.items;
        var tableCommandNames = this._tableCommands;
        for (var name in items) {
            var item = items[name];
            var toggleState = item.get_toggleState();
            if (toggleState == 1/*Typps.ToggleState.Down*/)
                this.release(name);
        }
        this._enableOrDisableByRange(tableCommandNames, 0/*Typps.Enable.False*/);
        this.releaseHighlight();
        this._clearActiveNode();
    },
    activeAll: function (elem) {
        //first reset
        this.releaseAll();
        var tableCommandNames = this._tableCommands;
        var items = this.items;
        var flag1 = false;
        var flag2 = false;
        var flag3 = false;
        var flag4 = false;
        var flag5 = false;
        var flag6 = false;
        var align = 'left'; /*in future do the same for direction and other commands*/
        do {
            var elemName = elem.nodeName.toLowerCase();
            if (elemName == 'body' || elemName == 'html') break;
            var item = this.get_toolBarItem(elemName);
            if (!flag1) {
                flag1 = (Array.indexOf(this._highlightNodeNames, elemName) != -1);
                this.highlightNode(elem);
            }
            if (!flag2 && item != null) {
                item.active();
                flag2 = true;
            }
            if (!flag3) {
                var value = this._getAttributeValue(elem, 'align', 'textAlign');
                if (value) {
                    align = value;
                    flag3 = true;
                }
            }
            /*special treatment for td. since we already have a reference, lets hold on to it.*/
            if (!flag4 && elemName == 'td') {
                this._activeNode['td'] = elem;
                this._enableOrDisableByRange(tableCommandNames, 1/*Typps.Enable.True*/);
                flag4 = true;
            }
            if (!flag5 && elemName == 'img') {
                this._activeNode['img'] = elem;
                flag5 = true;
            }
            if (!flag6 && elemName == 'a') {
                this._activeNode['a'] = elem;
                flag6 = true;
            }
            if (flag1 && flag2) break;
        }
        while (elem = elem.parentNode);

        var name = this._transformAlignToJustify(align);
        var item = this.item(name);
        if (item)
            item.active();

        var _document = this.get_document();
        var body = _document.body;
        if (body != null && this._isIE)
            body.focus();
        var commandNames = this._queryCommands;
        for (var i in commandNames) {
            var commandName = commandNames[i];
            var commandState = false;
            try {
                commandState = _document.queryCommandState(commandName);
                if (commandState)
                    this.items[commandName].active();
            }
            catch (exception) { commandState = false; }
        }
    },
    _syncronizeHighlightedNodes: function () {
        var _document = this.get_document();
        var nodes = _document.body.getElementsByTagName('*');
        var length = nodes.length;
        var className = this._className;

        for (var num1 = 0; num1 < length; num1++) {
            var node = nodes[num1];
            if (node.nodeType == 1/*ELEMENT_NODE*/) {
                var containsClass = this._containsCssClass(node, className);
                var highlightedNodes = this._highlightedNodes;
                if (containsClass) {
                    if (!Array.contains(highlightedNodes, node))
                        Array.add(highlightedNodes, node);
                }
            }
        }
    },
    releaseHighlight: function () {
        var className = this._className;
        var highlightedNodes = this._highlightedNodes;
        var length = highlightedNodes.length - 1;
        for (var num1 = length; num1 >= 0; num1--) {
            var node = highlightedNodes[num1];
            this._removeCssClass(node, className);
            Array.remove(highlightedNodes, node);
        }
    },
    highlightNode: function (elem) {
        var highlightedNodes = this._highlightedNodes;
        var className = this._className;
        var containsClass = this._containsCssClass(elem, className);
        if (!containsClass)
            this._addCssClass(elem, className);
        if (!Array.contains(highlightedNodes, elem))
            Array.add(highlightedNodes, elem);
    },

    get_toolBarItem: function (nodeName) {
        var items = this.items;
        for (var name in items) {
            var item = items[name];
            var nodeNames = item.get_nodeNames();
            for (var i in nodeNames) {
                if (nodeName == nodeNames[i])
                    return item;
            }
        }
        return null;
    },
    selectToolBarItem: function (name) {
        /*a slightly variated method to make items active but one that is groupName aware*/
        var item = this.item(name);
        if (item) {
            this._releaseByGroupName(item.get_groupName());
            if (item.get_toggleEnabled())
                item.active();
        }
    },
    _releaseByGroupName: function (groupName) {
        if (groupName && groupName != '') {
            groupName = groupName.toLowerCase();
            var items = this.items;
            for (var name in items) {
                var item = items[name];
                var itemGroupName = item.get_groupName().toLowerCase();
                if (itemGroupName != '' && itemGroupName == groupName)
                    item.release(true);
            }
        }
    },
    _transformAlignToJustify: function (name) {
        switch (name) {
            case 'left':
                return 'justifyleft';
            case 'center':
                return 'justifycenter';
            case 'right':
                return 'justifyright';
            case 'justify':
                return 'justifyfull';
        }
        return name;
    },
    dispose: function () {
        for (var i in this.items)
            this.items[i].dispose();
        var _document = this.get_document();
        var html = _document.childNodes[0];
        if (this._iframeBodyClickDelegate != null)
            Sys.UI.DomEvent.removeHandler(html, 'click', this._iframeBodyClickDelegate);
        delete this._iframeBodyClickDelegate;
        if (this._iframeBodyKeyUpDelegate != null)
            Sys.UI.DomEvent.removeHandler(html, 'keyup', this._iframeBodyKeyUpDelegate);
        delete this._iframeBodyKeyUpDelegate;

        Typps.ToggleManager.callBaseMethod(this, 'dispose');
    },
    initialize: function () {
        Typps.ToggleManager.callBaseMethod(this, 'initialize');
        var _document = this.get_document();
        var html = _document.childNodes[0];

        if (this._iframeBodyClickDelegate == null)
            this._iframeBodyClickDelegate = Function.createDelegate(this, this._iframeBodyClickHandler);
        if (this._iframeBodyKeyUpDelegate == null)
            this._iframeBodyKeyUpDelegate = Function.createDelegate(this, this._iframeBodyKeyUpHandler);
        Sys.UI.DomEvent.addHandler(html, 'click', this._iframeBodyClickDelegate);
        Sys.UI.DomEvent.addHandler(html, 'keyup', this._iframeBodyKeyUpDelegate);
    },
    _iframeBodyClickHandler: function (args) {
        var target = args.target;
        this.activeAll(target);
        var handler = this.get_events().getHandler('onautotoggle');
        if (handler)
            handler(this, args);
    },
    _iframeBodyKeyUpHandler: function (args) {
        if (args.keyCode == 13/*Enter key pressed*/) {
            //an unfortunate workaround but necessary
            this._syncronizeHighlightedNodes();
        }
    },
    _addCssClass: function (elem, className) {
        Typps.Utility.addRemoveClassName(elem, className, Typps.Perform.Add);
    },
    _removeCssClass: function (elem, className) {
        Typps.Utility.addRemoveClassName(elem, className, Typps.Perform.Remove);
    },
    _containsCssClass: function (elem, className) {
        return Typps.Utility.containsCssClass(elem, className);
    }
}
Typps.ToggleManager.registerClass('Typps.ToggleManager', Sys.Component, Typps.IComposite);

//Tabs
Typps.Tabs = function (element) {
    Typps.Tabs.initializeBase(this, [element]);
    this.items = {};
}
Typps.Tabs.prototype = {
    add: function (item) {
        var isImplemented = Typps.IButtonItem.isImplementedBy(item);
        if (!isImplemented)
            throw "Items you add to a Tabs must implement Typps.IButtonItem interface";
        var name = item.get_name();
        var node = item.get_element();
        var element = this.get_element();
        /*can we retrieve this element by id instead of uselessly hacking with getElementsByTagName?*/
        var container = element.getElementsByTagName('div')[0];
        container.appendChild(node);
        item._initialize();
        var selected = item.get_selected();
        if (selected)
            item.active();
        this.items[name] = item;
    },
    remove: function (name) {
        delete this.items[name];
    },
    item: function (name) {
        return this.items[name];
    },
    count: function () {
        var length = 0;
        for (var i in this.items)
            length++;
        return length;
    },
    select: function (name) {
        var items = this.items;
        var resetToggleState = true;
        for (var index in items)
            items[index].release(resetToggleState);
        items[name].active();
    },
    _addCssClass: function (elem, className) {
        Typps.Utility.addRemoveClassName(elem, className, Typps.Perform.Add);
    },
    dispose: function () {
        for (var i in this._items) {
            var item = this._items[i];
            item.dispose();
        }
        Typps.Tabs.callBaseMethod(this, 'dispose');
    },
    initialize: function () {
        Typps.Tabs.callBaseMethod(this, 'initialize');
        var element = this.get_element();
        var alignRTL = (this._direction == 1/*Typps.Editor.Dir.RTL*/);
        var mode = this._mode;
        if (mode == 0/*Typps.Editor.IconType.ImageSprites*/ && alignRTL)
            element.style.backgroundPosition = 'right center';
    }
}
Typps.Tabs.registerClass('Typps.Tabs', Typps.BarBase, Typps.IComposite);

//ToolBarItem
Typps.ToolBarItem = function (element) {
    Typps.ToolBarItem.initializeBase(this, [element]);
    this._nodeNames = []; //elements to observe
    this._groupName = null; /*items can be grouped in a similar fashion to radio buttons*/
    this._toggleEnabled = false;
}
Typps.ToolBarItem.prototype = {
    get_groupName: function () {
        return this._groupName;
    },
    set_groupName: function (value) {
        this._groupName = value;
    },
    get_toggleEnabled: function () {
        return this._toggleEnabled;
    },
    set_toggleEnabled: function (value) {
        this._toggleEnabled = value;
    },
    addNodeName: function (name) {
        Array.add(this._nodeNames, name);
    },
    get_nodeNames: function () {
        return this._nodeNames;
    },
    enable: function () {
        var mode = this._mode;
        this.set_enabled(true);
        var elem = this.get_element();
        elem.disabled = false;
        elem.style.cursor = 'pointer';
        this._addActionHandler();
        if (mode == 1) {//Typps.Editor.IconType.Icons
            elem.style.backgroundColor = '';
            this._setChroma();
            Typps.Utility.setTransparency(elem, 100);
        }
        else {
            this._resetImageSpriteBackground();
        }
    },
    disable: function () {
        this.set_enabled(false);
        this._disposeHandlers();
        this._fadeOutAndDisable();
    },
    dispose: function () {
        //finally dispose
        Typps.ToolBarItem.callBaseMethod(this, 'dispose');
    },
    initialize: function () {
        Typps.ToolBarItem.callBaseMethod(this, 'initialize');
    },
    _initialize: function () {
        /*we don't want to run this code on initialize immidiately, but rather make it callable from a ToolBarItem owner ( a toolbarset)*/
        var a = this.get_element();
        var name = this._name;
        var mode = this._mode;
        var marginLeft = this._marginLeft;
        var index = this._index;
        var className = this._className;
        var transparentImage = this._transparentImage;
        var separatorImage = this._separatorImage;
        var icon = this._icon;
        var divider = this._divider;
        var isOptions = this._isOptions;
        var direction = (this._direction == Typps.Editor.Dir.LTR) ? 'left' : 'right';
        var enabled = this._enabled;
        var iconSeparator = null;

        a.href = 'javascript:void(0);';
        a.style.textDecoration = 'none';
        this._addCssClass(a, className + (isOptions ? '-toolbarsetoptions' : '-toolbarbutton'));

        if (isOptions)
            Typps.Utility.setFloat(a, direction);

        if (mode == 0) {
            a.style.marginLeft = marginLeft + 'px';
            if (this._isIE && Sys.Browser.version == 6) {
                if (index == 0)
                    a.style.display = 'inline';
                //IE6 is problematic. fixing doubled float margin bug by using display:inline + use a
                //transparent bg to fix empty elements 
                Typps.Utility.setBackGroundImage(a, transparentImage, 'no-repeat', 'center center');
            }
        }
        else {
            if (icon != null)
                Typps.Utility.setBackGroundImage(a, icon, 'no-repeat', 'center center');
            if (divider) {
                iconSeparator = document.createElement('b');
                Typps.Utility.setBackGroundImage(iconSeparator, separatorImage, 'no-repeat', 'center right');
                Typps.Utility.setFloat(iconSeparator, direction);
                this._addCssClass(iconSeparator, className + '-toolbarbuttonseparator');
            }
        }
        /*retrieve values from self, this kind of workaround is no longer required*/
        a.title = this._title;
        //a.appendChild(document.createTextNode('\u00A0'));
        if (enabled) {
            this._addActionHandler();
            if (mode == 1)//Typps.Editor.IconType.Icons
                this._setChroma();
        }
        else {
            this._fadeOutAndDisable();
        }
        if (iconSeparator !== null) {
            a.parentNode.appendChild(iconSeparator);
            this._setChroma(iconSeparator);
        }
    }
}
Typps.ToolBarItem.registerClass('Typps.ToolBarItem', Typps.BarItemBase);

//TabItem
Typps.TabItem = function (element) {
    Typps.TabItem.initializeBase(this, [element]);
    this._selected = false;
}
Typps.TabItem.prototype = {
    get_selected: function () {
        return this._selected;
    },
    set_selected: function (value) {
        this._selected = value;
    },
    dispose: function () {
        //finally dispose
        Typps.TabItem.callBaseMethod(this, 'dispose');
    },
    initialize: function () {
        Typps.TabItem.callBaseMethod(this, 'initialize');
    },
    _initialize: function () {
        /*we don't want to run this code on initialize immidiately, but rather make it callable from a ToolBarItem owner ( a toolbarset)*/
        var a = this.get_element();
        var name = this._name;
        var mode = this._mode;
        var marginLeft = this._marginLeft;
        var index = this._index;
        var className = this._className;
        var transparentImage = this._transparentImage;
        var separatorImage = this._separatorImage;
        var icon = this._icon;
        var divider = this._divider;
        var isOptions = this._isOptions;
        var direction = (this._direction == Typps.Editor.Dir.LTR) ? 'left' : 'right';
        var enabled = this._enabled;
        var width = this._width; /*value with unit*/
        var title = this._title;
        a.href = 'javascript:void(0);';
        a.style.textDecoration = 'none';
        a.title = title;
        a.style.width = width;
        if (direction == 'right' && mode == 1/*Typps.Editor.IconType.Icons*/)
            Typps.Utility.setFloat(a, 'left');
        else
            Typps.Utility.setFloat(a, direction);
        var iconSeparator = null;
        if (mode == 0/*Typps.Editor.IconType.ImageSprites*/) {
            a.style.marginLeft = marginLeft + 'px';
            if (this._isIE && Sys.Browser.version == 6) {
                if (index == 0)
                    a.style.display = 'inline';
                Typps.Utility.setBackGroundImage(a, transparentImage, 'no-repeat', 'center center');
            }
        }
        else {
            Typps.Utility.setBackGroundImage(a, icon, 'no-repeat', 'center center');
            this._addCssClass(a, className + '-tabbutton');
            if (divider) {
                var iconSeparator = document.createElement('b');
                Typps.Utility.setFloat(iconSeparator, direction);
                Typps.Utility.setBackGroundImage(iconSeparator, separatorImage, 'no-repeat', 'center center');
                this._addCssClass(iconSeparator, className + '-tabbuttonseparator');
            }
        }
        if (enabled) {
            this._addActionHandler(a);
            this._setChroma(a);
        }
        else {
            this._fadeOutAndDisable(a);
        }

        if (iconSeparator !== null) {
            a.parentNode.appendChild(iconSeparator);
            this._setChroma(iconSeparator);
        }
    }
}
Typps.TabItem.registerClass('Typps.TabItem', Typps.BarItemBase);

Typps.Editor = function (element) {
    Typps.Editor.initializeBase(this, [element]);
    var id = this.get_id();
    this._eventArgument = null;
    this._editorText = $get(id + '_editortext');
    this._nonEditableHtml = $get(id + '_noneditablehtml');
    this._warningsLog = $get(id + '_warningslog');
    this._ignoreWords = $get(id + '_ignorewords');
    this._designArea = $get(id + '_designarea');
    this._shaderColor = '#000';
    this._shaderOpacity = 20;
    this._toolBarShadeColor = '#fff';
    this._callbacks = null;
    this._formatBlockLabel = null;
    this._toolBarCollection = null;
    this._tabCollection = null;
    this._toolBars = null;
    this._toggleManager = null;
    this._onAutoToggleDelegate = null;
    this._tabs = null;
    this._ignoreLabel = null;
    this._suggestionListHeaderTitle = 'Suggestion';
    this._ddlSelectDelegate = null;
    this._ddlCloseDelegate = null;
    this._beginRequestHandlerDelegate = null;
    this._endRequestHandlerDelegate = null;
    this._className = null;
    this._timeout = 0;
    this._cssListEnabled = false;
    this._dictionaryEnabled = false;
    this._activeTab = null;
    this._enableToolBarFloat = false;
    this._updatePanelProgressId = null;
    this._disabledButtonBackColor = null;
    this._disabledButtonTransparency = null;
    this._disabledButtonBorderColor = null;
    this._toolBarSeparatorImage = null;
    this._tabLeftBorderImage = null;
    this._tabOptionsImage = null;
    this._mode = null;
    this._imagePickerId = null;
    this._colorPickerId = null;
    this._postbackAllFormData = false;
    this._cssClassIdentifiers = '';
    this._externalStyleSheet = '';
    this._externalStyleSheets = '';
    this._externalStyleSheetReferences = '';
    this._dataFileUrl = null;
    this._direction = null;
    this._autoSwitchTextDirection = null;
    this._htmlHighlightCssClass = null;
    this._transparentImageUrl = null;
    this._autoResolveToAbsolutePath = false;
    this._fileUploadRequiredMessage = null;
    this._autoPromptMultiFileUpload = false;
    this._multiFileUploaderProgress = null;
    this._fileRemoveImageUrl = null;
    this._fileUploadingMessage = null;
    this._enableFileBrowser = false;
    this._enableFileUpload = true;
    this._fileUploadMimeFilter = null;
    this._multiFileUploadMimeFilter = null;
    this._uniqueId = null;
    this._height = '200px';
    this._width = null;
    this._toolbarContainerId = null;
    this._enableDropDownListEffects = true;
    this._dropDownListEffectDuration = 250;
    this._maxLength = 0;
    this._fontNames = ['Helvetica', 'Impact', 'Tahoma', 'Verdana', 'Courier New', 'Microsoft Sans Serif', 'Times New Roman', 'Arial', 'Geneva', 'Comic Sans MS', 'Trebuchet MS'];
}

Typps.Editor.prototype = {
	get_uniqueId: function () {
		return this._uniqueId;
	},
	set_uniqueId: function (value) {
		this._uniqueId = value;
	},
	get_updatePanelProgressId: function () {
		return this._updatePanelProgressId;
	},
	set_updatePanelProgressId: function (value) {
		this._updatePanelProgressId = value;
	},
	get_callbacks: function () {
		return this._callbacks;
	},
	set_callbacks: function (value) {
		this._callbacks = value;
	},
	get_className: function () {
		return this._className;
	},
	set_className: function (value) {
		this._className = value;
	},
	get_formatBlockLabel: function () {
		return this._formatBlockLabel;
	},
	set_formatBlockLabel: function (value) {
		this._formatBlockLabel = value;
	},
	get_toolBarCollection: function () {
		return this._toolBarCollection;
	},
	set_toolBarCollection: function (value) {
		this._toolBarCollection = value;
	},
	get_tabCollection: function () {
		return this._tabCollection;
	},
	set_tabCollection: function (value) {
		this._tabCollection = value;
	},
	get_toolBars: function () {
		return this._toolBars;
	},
	get_toggleManager: function () {
		return this._toggleManager;
	},
	get_tabs: function () {
		return this._tabs;
	},
	get_shaderColor: function () {
		return this._shaderColor;
	},
	set_shaderColor: function (value) {
		this._shaderColor = value;
	},
	get_shaderOpacity: function () {
		return this._shaderOpacity;
	},
	set_shaderOpacity: function (value) {
		this._shaderOpacity = value;
	},
	get_toolBarShadeColor: function () {
		return this._toolBarShadeColor;
	},
	set_toolBarShadeColor: function (value) {
		this._toolBarShadeColor = value;
	},
	get_ignoreLabel: function () {
		return this._ignoreLabel;
	},
	set_ignoreLabel: function (value) {
		this._ignoreLabel = value;
	},
	get_suggestionListHeaderTitle: function () {
		return this._suggestionListHeaderTitle;
	},
	set_suggestionListHeaderTitle: function (value) {
		this._suggestionListHeaderTitle = value;
	},
	get_timeout: function () {
		return this._timeout;
	},
	set_timeout: function (value) {
		this._timeout = value;
	},
	get_cssListEnabled: function () {
		return this._cssListEnabled;
	},
	set_cssListEnabled: function (value) {
		this._cssListEnabled = value;
	},
	get_dictionaryEnabled: function () {
		return this._dictionaryEnabled;
	},
	set_dictionaryEnabled: function (value) {
		this._dictionaryEnabled = value;
	},
	get_enableToolBarFloat: function () {
		return this._enableToolBarFloat;
	},
	set_enableToolBarFloat: function (value) {
		this._enableToolBarFloat = value;
	},
	get_disabledButtonBackColor: function () {
		return this._disabledButtonBackColor;
	},
	set_disabledButtonBackColor: function (value) {
		this._disabledButtonBackColor = value;
	},
	get_disabledButtonTransparency: function () {
		return this._disabledButtonTransparency;
	},
	set_disabledButtonTransparency: function (value) {
		this._disabledButtonTransparency = value;
	},
	get_disabledButtonBorderColor: function () {
		return this._disabledButtonBorderColor;
	},
	set_disabledButtonBorderColor: function (value) {
		this._disabledButtonBorderColor = value;
	},
	get_toolBarSeparatorImage: function () {
		return this._toolBarSeparatorImage;
	},
	set_toolBarSeparatorImage: function (value) {
		this._toolBarSeparatorImage = value;
	},
	get_tabLeftBorderImage: function () {
		return this._tabLeftBorderImage;
	},
	set_tabLeftBorderImage: function (value) {
		this._tabLeftBorderImage = value;
	},
	get_tabOptionsImage: function () {
		return this._tabOptionsImage;
	},
	set_tabOptionsImage: function (value) {
		this._tabOptionsImage = value;
	},
	get_mode: function () {
		return this._mode;
	},
	set_mode: function (value) {
		this._mode = value;
	},
	get_imagePickerId: function () {
		return this._imagePickerId;
	},
	set_imagePickerId: function (value) {
		this._imagePickerId = value;
	},
	get_colorPickerId: function () {
		return this._colorPickerId;
	},
	set_colorPickerId: function (value) {
		this._colorPickerId = value;
	},
	get_formElementId: function () {
		return this._formElementId;
	},
	set_formElementId: function (value) {
		this._formElementId = value;
	},
	get_postbackAllFormData: function () {
		return this._postbackAllFormData;
	},
	set_postbackAllFormData: function (value) {
		this._postbackAllFormData = value;
	},
	get_cssClassIdentifiers: function () {
		return this._cssClassIdentifiers;
	},
	set_cssClassIdentifiers: function (value) {
		this._cssClassIdentifiers = value;
	},
	get_externalStyleSheet: function () {
		return this._externalStyleSheet;
	},
	set_externalStyleSheet: function (value) {
		this._externalStyleSheet = value;
	},
	get_externalStyleSheets: function () {
		return this._externalStyleSheets;
	},
	set_externalStyleSheets: function (value) {
		this._externalStyleSheets = value;
	},
	get_externalStyleSheetReferences: function () {
		return this._externalStyleSheetReferences;
	},
	set_externalStyleSheetReferences: function (value) {
		this._externalStyleSheetReferences = value;
	},
	get_direction: function () {
		return this._direction;
	},
	set_direction: function (value) {
		this._direction = value;
	},
	get_autoSwitchTextDirection: function () {
		return this._autoSwitchTextDirection;
	},
	set_autoSwitchTextDirection: function (value) {
		this._autoSwitchTextDirection = value;
	},
	get_transparentImageUrl: function () {
		return this._transparentImageUrl;
	},
	set_transparentImageUrl: function (value) {
		this._transparentImageUrl = value;
	},
	get_enableDropDownListEffects: function () {
		return this._enableDropDownListEffects;
	},
	set_enableDropDownListEffects: function (value) {
		this._enableDropDownListEffects = value;
	},
	get_dropDownListEffectDuration: function () {
		return this._dropDownListEffectDuration;
	},
	set_dropDownListEffectDuration: function (value) {
		this._dropDownListEffectDuration = value;
	},
	get_fontNames: function () {
		return this._fontNames;
	},
	set_fontNames: function (value) {
		this._fontNames = value;
	},
	get_maxLength: function () {
		return this._maxLength;
	},
	set_maxLength: function (value) {
		this._maxLength = value;
	},
	get_dataFileUrl: function () {
		return this._dataFileUrl;
	},
	set_dataFileUrl: function (value) {
		this._dataFileUrl = value;
	},
	get_htmlText: function () {
		this._fillEmptyBlockElements();
		if (this.isIE)
			this._ensureImgWidthAndHeight();
		var text = this.iframe.body.innerHTML;
		text = this.tokenizeUrls(Typps.Perform.Remove, text);
		if (!this._isIE || text.length == 0) return text;
		var index = text.toLowerCase().indexOf('<br>', 0);
		if (index == 0 && text.toLowerCase().indexOf('<script', index) != -1)
			return text.substr(4);
		return text;
	},
	set_htmlText: function (value) {
		var text = value.trim();
		if (this._isIE && text.toLowerCase().indexOf('<script') == 0) {
			/*stops awkward stripping of script tags.*/
			text = '<br />' + text;
		}
		text = this.tokenizeUrls(Typps.Perform.Add, text);
		this.iframe.body.innerHTML = text;
		this._focusFirstChild();
		this._fillEmptyBlockElements();
		this._normalizeBlockQuotes();
	},
	get_autoResolveToAbsolutePath: function () {
		return this._autoResolveToAbsolutePath;
	},
	set_autoResolveToAbsolutePath: function (value) {
		this._autoResolveToAbsolutePath = value;
	},
	get_fileUploadRequiredMessage: function () {
		return this._fileUploadRequiredMessage;
	},
	set_fileUploadRequiredMessage: function (value) {
		this._fileUploadRequiredMessage = value;
	},
	get_autoPromptMultiFileUpload: function () {
		return this._autoPromptMultiFileUpload;
	},
	set_autoPromptMultiFileUpload: function (value) {
		this._autoPromptMultiFileUpload = value;
	},
	get_multiFileUploaderProgress: function () {
		return this._multiFileUploaderProgress;
	},
	set_multiFileUploaderProgress: function (value) {
		this._multiFileUploaderProgress = value;
	},
	get_fileRemoveImageUrl: function () {
		return this._fileRemoveImageUrl;
	},
	set_fileRemoveImageUrl: function (value) {
		this._fileRemoveImageUrl = value;
	},
	get_fileUploadingMessage: function () {
		return this._fileUploadingMessage;
	},
	set_fileUploadingMessage: function (value) {
		this._fileUploadingMessage = value;
	},
	get_enableFileBrowser: function () {
		return this._enableFileBrowser;
	},
	set_enableFileBrowser: function (value) {
		this._enableFileBrowser = value;
	},
	get_enableFileUpload: function () {
		return this._enableFileUpload;
	},
	set_enableFileUpload: function (value) {
		this._enableFileUpload = value;
	},
	get_fileUploadMimeFilter: function () {
		return this._fileUploadMimeFilter;
	},
	set_fileUploadMimeFilter: function (value) {
		this._fileUploadMimeFilter = value;
	},
	get_multiFileUploadMimeFilter: function () {
		return this._multiFileUploadMimeFilter;
	},
	set_multiFileUploadMimeFilter: function (value) {
		this._multiFileUploadMimeFilter = value;
	},
	get_height: function () {
		return this._height;
	},
	set_height: function (value) {
		if (!Typps.Utility.isNullOrEmpty(value))
			this._height = value;
	},
	get_width: function () {
		return this._width;
	},
	set_width: function (value) {
		this._width = value;
	},
	get_toolbarContainerId: function () {
		return this._toolbarContainerId;
	},
	set_toolbarContainerId: function (value) {
		this._toolbarContainerId = value;
	},
	add_popupCloseButton: function (handler) {
		this.get_events().addHandler('popupClose', handler);
	},
	remove_popupCloseButton: function (handler) {
		this.get_events().removeHandler('popupClose', handler);
	},
	add_colorSelect: function (handler) {
		this.get_events().addHandler('colorSelect', handler);
	},
	remove_colorSelect: function (handler) {
		this.get_events().removeHandler('colorSelect', handler);
	},
	add_ddlSelect: function (handler) {
		this.get_events().addHandler('ddlSelect', handler);
	},
	remove_ddlSelect: function (handler) {
		this.get_events().removeHandler('ddlSelect', handler);
	},

	add_ddlClose: function (handler) {
		this.get_events().addHandler('ddlClose', handler);
	},
	remove_ddlClose: function (handler) {
		this.get_events().removeHandler('ddlClose', handler);
	},

	add_beginWebRequest: function (handler) {
		this.get_events().addHandler('beginWebRequest', handler);
	},
	remove_beginWebRequest: function (handler) {
		this.get_events().removeHandler('beginWebRequest', handler);
	},

	add_endWebRequest: function (handler) {
		this.get_events().addHandler('endWebRequest', handler);
	},
	remove_endWebRequest: function (handler) {
		this.get_events().removeHandler('endWebRequest', handler);
	},
	add_toolBarItemClick: function (handler) {
		this.get_events().addHandler('toolbaritemclick', handler);
	},
	remove_toolBarItemClick: function (handler) {
		this.get_events().removeHandler('toolbaritemclick', handler);
	},
	add_tabItemClick: function (handler) {
		this.get_events().addHandler('tabitemclick', handler);
	},
	remove_tabItemClick: function (handler) {
		this.get_events().removeHandler('tabitemclick', handler);
	},
	add_toolBarOptionItemClick: function (handler) {
		this.get_events().addHandler('toolbaroptionitemclick', handler);
	},
	remove_toolBarOptionItemClick: function (handler) {
		this.get_events().removeHandler('toolbaroptionitemclick', handler);
	},
	add_maxLengthReached: function (handler) {
		this.get_events().addHandler('maxlengthreached', handler);
	},
	remove_maxLengthReached: function (handler) {
		this.get_events().removeHandler('maxlengthreached', handler);
	},
	add_saving: function (handler) {
		this.get_events().addHandler('saving', handler);
	},
	remove_saving: function (handler) {
		this.get_events().removeHandler('saving', handler);
	},
	add_saved: function (handler) {
		this.get_events().addHandler('saved', handler);
	},
	remove_saved: function (handler) {
		this.get_events().removeHandler('saved', handler);
	},
	// Release resources before control is disposed.
	dispose: function () {
		var element = this.get_element();
		var id = this.get_id();
		var fontName = $get(id + '_ddlfontname');
		var fontSize = $get(id + '_ddlfontsize');
		var formatBlock = $get(id + '_ddlformatblock');

		// updatepanel events
		if (this._beginRequestHandlerDelegate) { delete this._beginRequestHandlerDelegate; }
		if (this._beginRequestHandlerDelegate) { delete this._endRequestHandlerDelegate; }
		// table editor events
		if (this._ckTableWidthDelegate) {
			Sys.UI.DomEvent.removeHandler($get(this._tableDesignerId + '_ckwidth'), 'click', this._ckTableWidthDelegate);
			delete this._ckTableWidthDelegate;
		}
		if (this._ckTableHeightDelegate) {
			Sys.UI.DomEvent.removeHandler($get(this._tableDesignerId + '_ckheight'), 'click', this._ckTableHeightDelegate);
			delete this._ckTableHeightDelegate;
		}
		if (this._ckTableBorderDelegate) {
			Sys.UI.DomEvent.removeHandler($get(this._tableDesignerId + '_ckborder'), 'click', this._ckTableBorderDelegate);
			delete this._ckTableBorderDelegate;
		}
		if (this._ckTablePaddingDelegate) {
			Sys.UI.DomEvent.removeHandler($get(this._tableDesignerId + '_ckpadding'), 'click', this._ckTablePaddingDelegate);
			delete this._ckTablePaddingDelegate;
		}
		if (this._ckTableSpacingDelegate) {
			Sys.UI.DomEvent.removeHandler($get(this._tableDesignerId + '_ckspacing'), 'click', this._ckTableSpacingDelegate);
			delete this._ckTableSpacingDelegate;
		}
		if (this._btnTableBorderColorDelegate) {
			Sys.UI.DomEvent.removeHandler($get(this._tableDesignerId + '_btnbordercolor'), 'click', this._btnTableBorderColorDelegate);
			delete this._btnTableBorderColorDelegate;
		}
		if (this._btnTableBackgroundColorDelegate) {
			Sys.UI.DomEvent.removeHandler($get(this._tableDesignerId + '_btnbackgroundcolor'), 'click', this._btnTableBackgroundColorDelegate);
			delete this._btnTableBackgroundColorDelegate;
		}
		if (this._btnTableAddNewDelegate) {
			Sys.UI.DomEvent.removeHandler($get(this._tableDesignerId + '_btnaddnew'), 'click', this._btnTableAddNewDelegate);
			delete this._btnTableAddNewDelegate;
		}
		if (this._btnTableOkDelegate)
			delete this._btnTableOkDelegate;
		if (this._btnTableCancelDelegate)
			delete this._btnTableCancelDelegate;
		if (this._ckCellWidthDelegate) {
			Sys.UI.DomEvent.removeHandler($get(this._cellDesignerId + '_ckwidth'), 'click', this._ckCellWidthDelegate);
			delete this._ckCellWidthDelegate;
		}
		if (this._ckCellHeightDelegate) {
			Sys.UI.DomEvent.removeHandler($get(this._cellDesignerId + '_ckheight'), 'click', this._ckCellHeightDelegate);
			delete this._ckCellHeightDelegate;
		}
		if (this._ckTableCellBorderDelegate) {
			Sys.UI.DomEvent.removeHandler($get(this._cellDesignerId + '_ckborder'), 'click', this._ckTableCellBorderDelegate);
			delete this._ckTableCellBorderDelegate;
		}
		if (this._btnCellBackGroundColorDelegate) {
			Sys.UI.DomEvent.removeHandler($get(this._cellDesignerId + '_btnbackgroundcolor'), 'click', this._btnCellBackGroundColorDelegate);
			delete this._btnCellBackGroundColorDelegate;
		}
		if (this._btnCellBorderColorDelegate) {
			Sys.UI.DomEvent.removeHandler($get(this._cellDesignerId + '_btnbordercolor'), 'click', this._btnCellBorderColorDelegate);
			delete this._btnCellBorderColorDelegate;
		}
		if (this._btnCellOkDelegate)
			delete this._btnCellOkDelegate;
		if (this._btnCellCancelDelegate)
			delete this._btnCellCancelDelegate;

		if (this._btnImageDesignerOkDelegate)
			delete this._btnImageDesignerOkDelegate;
		if (this._btnImageDesignerCancelDelegate)
			delete this._btnImageDesignerCancelDelegate;
		//insert image designer
		if (this._btnHyperlinkloaderOkDelegate)
			delete this._btnHyperlinkloaderOkDelegate;
		if (this._btnHyperlinkloaderCancelDelegate)
			delete this._btnHyperlinkloaderCancelDelegate;
		if (this._btnBrowseServerDelegate) {
			Sys.UI.DomEvent.removeHandler($get(this._hyperlinkId + '_btnbrowse'), 'click', this._btnBrowseServerDelegate);
			delete this._btnBrowseServerDelegate;
		}
		if (this._hyperlinkTypeChangeDelegate) {
			Sys.UI.DomEvent.removeHandler($get(this._hyperlinkId + '_type'), 'change', this._hyperlinkTypeChangeDelegate);
			delete this._hyperlinkTypeChangeDelegate;
		}
		if (this._codeHilighterOkDelegate)
			this._codeHilighterWindow.remove_okButton(this._codeHilighterOkDelegate);
		if (this._codeHilighterCancelDelegate)
			this._codeHilighterWindow.remove_cancelButton(this._codeHilighterCancelDelegate);

		if (this._wordCleanupOkDelegate)
			this._wordCleanupWindow.remove_okButton(this._wordCleanupOkDelegate);
		if (this._wordCleanupCancelDelegate)
			this._wordCleanupWindow.remove_cancelButton(this._wordCleanupCancelDelegate);

		this._disposeSuggestionDropDownList(null); // first clear all suggestion dropdownlists, if any.
		this._disposeSpellCheckerElements(); // then remove any previously spell checked items
		this._disposeTreeView();

		var toolBars = this.get_toolBars();
		if (toolBars) toolBars.dispose();

		var tabs = this._tabs;
		if (tabs) tabs.dispose();

		if (this.rangeComponent) {
			this.rangeComponent.dispose();
			delete this.rangeComponent;
		}
		if (this._onResizeHandlerDelegate) {
			Sys.UI.DomEvent.removeHandler(window, 'resize', this._onResizeHandlerDelegate);
			delete this._onResizeHandlerDelegate;
		}
		if (this._onScrollDelegate) {
			Sys.UI.DomEvent.removeHandler(window, 'scroll', this._onScrollDelegate);
			delete this._onScrollDelegate;
		}
		if (this._hyperlinkWindow) {
			this._hyperlinkWindow.dispose();
			delete this._hyperlinkWindow;
		}
		if (this._codeHilighterWindow) {
			this._codeHilighterWindow.dispose();
			delete this._codeHilighterWindow;
		}
		if (this._codeHilighterWindow) {
			this._codeHilighterWindow.dispose();
			delete this._codeHilighterWindow;
		}
		if (this._wordCleanupWindow) {
			this._wordCleanupWindow.dispose();
			delete this._wordCleanupWindow;
		}
		if (this._dropDownListSpellChecker) {
			this._dropDownListSpellChecker.dispose();
			delete this._dropDownListSpellChecker;
		}
		if (this._spellCheckerCompleteMessagePopup) {
			this._spellCheckerCompleteMessagePopup.dispose();
			delete this._spellCheckerCompleteMessagePopup;
		}
		if (this._cssClassNamesList) {
			this._cssClassNamesList.dispose();
			delete this._cssClassNamesList;
		}

		var html = this.iframe.childNodes[0];
		if (this._iframeBodyClickDelegate != null)
			Sys.UI.DomEvent.removeHandler(html, 'click', this._iframeBodyClickDelegate);
		delete this._iframeBodyClickDelegate;

		if (this._toggleManager)
			this._toggleManager.dispose();

		delete this.iframe;
		Typps.Editor.callBaseMethod(this, 'dispose');
	},
	_disposeTreeView: function () {
		if (this._toggleTreeViewStateDelegate) {
			var treeview = $get(this.get_id() + '_treeview');
			var rootElements = new Array();
			var leafElements = new Array();
			var num1 = 0;
			var classNames1 = { a: 'nodecollapse', b: 'nodeexpand', c: 'clickablenonlink' };
			var classNames2 = { a: 'nonlink' };
			this._getElementsByClassName(treeview, 'span', classNames1, rootElements);
			this._getElementsByClassName(treeview, 'b', classNames1, rootElements);
			this._getElementsByClassName(treeview, 'span', classNames2, leafElements);
			if (this._toggleTreeViewStateDelegate) {
				for (num1 = 0; num1 < rootElements.length; num1++) {
					var span = rootElements[num1];
					if (this._toggleTreeViewStateDelegate != null)
						Sys.UI.DomEvent.removeHandler(span, 'click', this._toggleTreeViewStateDelegate);
				}
				delete this._toggleTreeViewStateDelegate;
				this._toggleTreeViewStateDelegate = null;
			}
			if (this._leafNodeClickDelegate) {
				for (num1 = 0; num1 < leafElements.length; num1++) {
					span = leafElements[num1];
					if (this._leafNodeClickDelegate)
						Sys.UI.DomEvent.removeHandler(span, 'click', this._leafNodeClickDelegate);
				}
				delete this._leafNodeClickDelegate;
				this._leafNodeClickDelegate = null;
			}
			if (treeview != null)
				treeview.parentNode.removeChild(treeview);
		}
	},
	initialize: function () {
		Typps.Editor.callBaseMethod(this, 'initialize');
		var id = this.get_id();
		this._isIE = (Sys.Browser.agent == Sys.Browser.InternetExplorer);
		this._isFF = (Sys.Browser.agent == Sys.Browser.Firefox);
		this._isOpera = (Sys.Browser.agent == Sys.Browser.Opera);
		this._isWebKit = (Sys.Browser.agent == Sys.Browser.WebKit);

		this._currentTabView = 0; /*Typps.Editor.TabView.DesignView*/
		this._isHtmlDirty = false;
		this._editableTableCell = null;
		this.iframe = null;
		this.contentWindow = null;
		this._request = null;
		this.rangeComponent = null;
		this._iframeBodyClickDelegate = null;
		this._toolBarItemClickDelegate = null;
		this._toolBarOptionItemClickDelegate = null;
		this._tabItemClickDelegate = null;
		this._displayErrorLogMessage = true;
		this._errorsLoggedMessagePopup = null;
		this._multiFileUploaderWindow = null;
		this._btnMultiFileUploaderOkDelegate = null;
		this._btnMultiFileUploaderCancelDelegate = null;
		this._btnMultiFileUploaderAddNewDelegate = null;
		this._iframeMultiFileUploadLoadDelegate = null;
		this._multiFileRemoveInputDelegate = null;
		this._warningsLogShowDelegate = null;
		this._warningsLogMessageOkDelegate = null;
		this._dropDownListFontName = null;
		this._dropDownListFontSize = null;
		this._dropDownListFormatBlock = null;
		this._colorSelectDelegate = null;
		this._ckTableWidthDelegate = null;
		this._ckTableHeightDelegate = null;
		this._ckTableBorderDelegate = null;
		this._ckTablePaddingDelegate = null;
		this._ckTableSpacingDelegate = null;
		this._btnTableBorderColorDelegate = null;
		this._btnTableBackgroundColorDelegate = null;
		this._btnTableAddNewDelegate = null;
		this._btnTableOkDelegate = null;
		this._btnTableCancelDelegate = null;
		this._ckCellWidthDelegate = null;
		this._ckCellHeightDelegate = null;
		this._btnCellBorderColorDelegate = null;
		this._btnCellBackGroundColorDelegate = null;
		this._ckTableCellBorderDelegate = null;
		this._btnCellOkDelegate = null;
		this._btnCellCancelDelegate = null;
		this._btnImageDesignerOkDelegate = null;
		this._btnImageDesignerCancelDelegate = null;
		this._hyperlinkTypeChangeDelegate = null;
		this._btnHyperlinkloaderOkDelegate = null;
		this._btnHyperlinkloaderCancelDelegate = null;
		this._btnBrowseServerDelegate = null;
		this._hyperlinkElement = null;
		this._codeHilighterOkDelegate = null;
		this._codeHilighterCancelDelegate = null;
		this._fileBrowserWindow = null;
		this._btnFileBrowserOkDelegate = null;
		this._btnFileBrowserCancelDelegate = null;
		this._btnFileBrowserUploadDelegate = null;
		this._btnFileUploaderOkDelegate = null;
		this._btnFileUploaderDelegate = null;
		this._iframeFileUploadDelegate = null;
		this._selectedFileUrl = null;
		this._tabId = id + '_tabs';
		this._fileBrowserId = id + '_filebrowser';
		this._fileUploaderId = id + '_fileupload';
		this._cellDesignerId = id + '_celldesigner';
		this._tableDesignerId = id + '_tabledesigner';
		this._hyperlinkId = id + '_hyperlink';
		this._codeHilighterId = id + '_codehilighter';
		this._multiFileUploaderId = id + '_multifileuploader';
		this._lastMultiFileInputIndex = 0;
		this._hyperlinkWindow = null;
		this._tableDesignerWindow = null;
		this._cellDesignerWindow = null;
		this._imageDesigner = null;
		this._colorPicker = null;
		this._btnColorPickerOkDelegate = null;
		this._btnColorPickerCancelDelegate = null;

		this._colorWindow = null;
		this._codeHilighterWindow = null;
		this._wordCleanupWindow = null;
		this._wordCleanupId = id + '_wordcleanup';
		this._wordCleanupOkDelegate = null;
		this._wordCleanupCancelDelegate = null;

		this._dropDownListSpellChecker = null;
		this._ddlSpellCheckerSelectDelegate = null;
		this._ddlSpellCheckerCloseDelegate = null;
		this._dropDownListMisspellWord = null;
		this._ddlMisspellWordSelectDelegate = null;
		this._ddlMisspellWordMenuSelectedDelegate = null;
		this._ddlMisspellWordCloseDelegate = null;
		this._misspellWordClickDelegate = null;
		this._dictionaryDropDownListCollection = null;
		this._displaySpellingCompleteMessage = true;
		this._spellCheckerCompleteMessagePopup = null;
		this._spellCheckerCompleteMessageOkDelegate = null;
		this._cssClassNamesList = null;
		this._ddlCssClassNamesListSelectDelegate = null;
		this._ddlCssClassNamesListCloseDelegate = null;
		this._frameLoadDelegate = null;
		this._blockElementOnClickDelegate = null;
		this._floatingToolBarCloseButtonDelegate = null;
		this._htmlViewDoubleClickDelegate = null;

		this._toggleTreeViewStateDelegate = null;
		this._leafNodeClickDelegate = null;
		this._htmlHighlightCssClass = this._className + '-htmlelementhighlightstyle';
		this._selectedDictionary = null;
		this._pageLoadDelegate = null;
		this._updatePanelProgress = null;
		this._lastRange = null;
		this._urls = null;
		this._lastCommand = null;
		this.iframeElement = this._getIframe(id + '_frame', this._designArea, true);
		this._multiFileActivation = null;

		if (this.iframeElement != null) {
			if (this._frameLoadDelegate == null) {
				this._frameLoadDelegate = Function.createDelegate(this, this._frameLoadHandler);
				Sys.UI.DomEvent.addHandler(this.iframeElement, 'load', this._frameLoadDelegate);
			}
		}

		this._form = Typps.Utility.getForm(this._formElementId);

		if (this._onResizeHandlerDelegate == null) {
			this._onResizeHandlerDelegate = Function.createDelegate(this, this._onResizeHandler);
			Sys.UI.DomEvent.addHandler(window, 'resize', this._onResizeHandlerDelegate);
		}
		if (this._onScrollDelegate == null) {
			this._onScrollDelegate = Function.createDelegate(this, this._onScrollHandler);
			Sys.UI.DomEvent.addHandler(window, 'scroll', this._onScrollDelegate);
		}
	},
	tokenizeUrls: function (operation, htmlText) {
		if (!this._isIE || this._autoResolveToAbsolutePath) return htmlText;
		htmlText = this._tokenizeSrc(operation, htmlText);
		htmlText = this._tokenizeHref(operation, htmlText);
		return htmlText;
	},
	_tokenizeSrc: function (operation, htmlText) {
		var re = /<img[^>]+src="([^"]+)"[^>]*>/gi;
		var lit1 = 'src="{0}"';
		var lit2 = 'src="{0}" src2="{0}"';
		if (operation == 1) {
			re = /<img[^>]+src2="([^"]+)"[^>]*>/gi;
			lit1 = '<[Ii][Mm][Gg] (src="[^"]+") (src2="{0}").*?>';
			lit2 = 'src="{0}"';
		}
		return this._beginTokenizeUrls(re, htmlText, lit1, lit2, operation);
	},
	_tokenizeHref: function (operation, htmlText) {
		var re = /<a[^>]+href="([^"]+)"[^>]*>/gi;
		var lit1 = 'href="{0}"';
		var lit2 = 'href="{0}" href2="{0}"';
		if (operation == 1) {
			re = /<a[^>]+href2="([^"]+)"[^>]*>/gi;
			lit1 = '<[Aa] (href="[^"]+") (href2="{0}").*?>';
			lit2 = 'href="{0}"';
		}
		return this._beginTokenizeUrls(re, htmlText, lit1, lit2, operation);
	},
	_beginTokenizeUrls: function (re, htmlText, lit1, lit2, operation) {
		var m = re.exec(htmlText);
		var t = htmlText;
		while (m != null) {
			var m1 = Typps.Utility.regExpEscape(m[1]);
			if (operation == 0) {
				t = t.replace(new RegExp(String.format(lit1, m1), 'gi'),
                    String.format(lit2, m[1]));
			} else {
				var match = t.match(new RegExp(String.format(lit1, m1)));
				if (match != null && match.length == 3) {
					t = t.replace(match[1], String.format(lit2, m[1]));
					t = t.replace(' ' + match[2], '');
				}
			}
			m = re.exec(htmlText);
		}
		return t;
	},
	_prepareForPostback: function () {
		this._toggleManager.releaseAll();
		var htmlText = this.get_htmlText();
		this._setDesignViewMode(htmlText);
		this._toolBarShaderShow(false);
		this._editorText.value = htmlText;
		this._currentTabView = Typps.Editor.TabView.DesignView;
	},
	_frameLoadHandler: function (args) {
		this._initialize();
	},
	_initialize: function () {
		var id = this.get_id();
		this.iframe = this.iframeElement.contentWindow.document;
		this.contentWindow = this.iframeElement.contentWindow;
		if (this.rangeComponent == null)
			this.rangeComponent = $create(Typps.Range, { id: id + '_range', contentWindow: this.contentWindow }, null, null, null);
		this._iframeDefaults();
		this._initializeDetachableToolBar();

		this._buildToolBar();
		this._applyExplictToolBarItemWidth();
		this._buildTabs();

		this._htmlViewInitialize();
		this._dimention();

		this._element.style.visibility = 'visible';
		this.iframe.body.tabIndex = 1;

		var html = this.iframe.childNodes[0];
		if (this._iframeBodyClickDelegate == null)
			this._iframeBodyClickDelegate = Function.createDelegate(this, this._iframeBodyClickHandler);
		Sys.UI.DomEvent.addHandler(html, 'click', this._iframeBodyClickDelegate);

		var htmlText = this._paragraphWrappedInnerHTML(this._editorText.value);
		this.set_htmlText(htmlText);
		if (this._isFF) {
			try {
				this.iframe.execCommand('insertbronreturn', false, false);
			}
			catch (exception) { }
		}
	},
	_buildTabs: function () {
		var id = this.get_id();
		var element = $get(id + '_tabs');
		var tabCollection = this.get_tabCollection();
		if (!tabCollection || tabCollection.length == 0) {
			if (element != null)
				element.style.display = 'none';
			return;
		}
		var direction = (this._direction == Typps.Editor.Dir.LTR) ? 'left' : 'right';
		var mode = this._mode;
		var margin = 0;
		var distance = 0;
		var leftBorderImage = this._tabLeftBorderImage;
		var tabs = this.createTabs(leftBorderImage, null, null, null, element);
		var index = 0;
		var node = null;
		var disabledBackColor = this._disabledButtonBackColor;
		var disabledBorderColor = this._disabledButtonBorderColor;
		var disabledTransparency = this._disabledButtonTransparency;
		for (index in tabCollection) {
			var tabItem = tabCollection[index];
			var name = tabItem.command;
			var enabled = tabItem.enabled; /*tabItem.enabled ? 1 : 0 we don't need to do this. make sure all code paths are now handling a bool instead of this hack*/
			var marginLeft = tabItem.marginLeft;
			var width = tabItem.width;
			var divider = tabItem.divider;
			var icon = tabItem.icon;
			var title = tabItem.title;
			var selected = (name == 'designview');
			node = document.createElement('a');
			var iconSeparator = null;
			distance += marginLeft;
			if (this._tabItemClickDelegate === null)
				this._tabItemClickDelegate = Function.createDelegate(this, this._tabItemClick);
			var command = new Typps.Command(null/*TabItem internally has logic to make itself the sender when null*/, this._tabItemClickDelegate);
			var tabItem = this.createTabItem(name, divider, icon, marginLeft, index, title, false, enabled, 1/*Typps.BarItemType.TabItem*/, width, distance, selected,
                                                        disabledBackColor, disabledBorderColor, disabledTransparency, command, node);
			tabs.add(tabItem);
			if (mode == 0/*Typps.Editor.IconType.ImageSprites*/) {
				var parsedWidth = parseInt(width);
				if (isNaN(parsedWidth)) parsedWidth = 0;
				distance += parsedWidth;
			}
		}
		this._tabs = tabs;
	},
	_buildToolBar: function () {
		var id = this.get_id();
		this._toolBars = new Typps.ToolBars();
		if (this._onAutoToggleDelegate == null)
			this._onAutoToggleDelegate = Function.createDelegate(this, this._onAutoToggleHandler);

		this._toggleManager = $create(Typps.ToggleManager,
        {
        	id: id + '_togglemanager',
        	document: this.iframe,
        	className: this._htmlHighlightCssClass
        }, {
        	onAutoToggle: this._onAutoToggleDelegate
        }, null, null);

		var toolBarCollection = this.get_toolBarCollection();
		var mode = this._mode;

		var averageIconWidth = null; //only utilized by imagesprites(NOTE: icons must all have the same width, a restriction in imagesprites mode).

		var disabledBackColor = this._disabledButtonBackColor;
		var disabledBorderColor = this._disabledButtonBorderColor;
		var disabledTransparency = this._disabledButtonTransparency;
		for (var i in toolBarCollection) {
			var tbs = toolBarCollection[i];
			var optionName = tbs.optionsName;
			var leftBorderImage = tbs.leftBorderImage;
			var optionsImage = tbs.optionsImage;
			var optionsTitle = tbs.optionsTitle;
			var element = $get(String.format("{0}_{1}", id, i));
			var toolBarSet = this.createToolBarSet(leftBorderImage, optionName,
                        optionsImage, optionsTitle, element);

			var j = 0;
			var node;
			var command;
			var distance = 0;
			for (j in tbs.items) {
				var tbi = tbs.items[j];
				node = document.createElement('a');
				var marginLeft = tbi.marginLeft;
				var toggleEnabled = tbi.toggleEnabled;
				var groupName = tbi.groupName;
				if (mode == 0/*Typps.Editor.IconType.ImageSprites*/) {
					distance += marginLeft;
				}
				var name = tbi.name;
				var enabled = tbi.enabled;
				if (enabled)
					enabled = this._enableToolBarItem(name); //process other rules if enabled

				if (this._toolBarItemClickDelegate === null)
					this._toolBarItemClickDelegate = Function.createDelegate(this, this._toolBarItemClick);
				command = new Typps.Command(null/*ToolBarItem internally has logic to make itself the sender when null*/, this._toolBarItemClickDelegate);
				var toolBarItem = this.createToolBarItem(name, tbi.divider, tbi.icon, marginLeft, j,
                    tbi.title, false, enabled, 0/*Typps.BarItemType.ToolBarItem*/, distance, toggleEnabled, groupName, disabledBackColor, disabledBorderColor, disabledTransparency, command, node);
				toolBarSet.add(toolBarItem);
				/*table editing commands are a special case since we want to enable them only when a td is the active node in designview*/
				var isTableCommand = Array.contains(this._toggleManager._tableCommands, name);
				if (toggleEnabled || isTableCommand)
					this._toggleManager.add(toolBarItem);

				if (mode == 0 && !averageIconWidth) {
					var style = Sys.UI.DomElement._getCurrentStyle(node);
					averageIconWidth = parseInt(style.width);
				}
			}
			var enableOptions = toolBarSet.get_enableOptions();
			if (enableOptions || mode == 0/*Typps.Editor.IconType.ImageSprites*/) {
				node = document.createElement('a');
				if (optionName == '')
					optionName = 'options';
				marginLeft = 1;
				distance++; //calculate the 1px margin
				var iconsCount = ++j;
				var groupName = '';
				/*special care for options, since it's the only icon that 
				has a different dimention (note all icons must have the same dimention
				in imagesprites mode, however options icon is special*/
				if (mode == 0/*Typps.Editor.IconType.ImageSprites*/)
					distance += (iconsCount * averageIconWidth); //the sum of all icons is the distance
				if (this._toolBarOptionItemClickDelegate === null)
					this._toolBarOptionItemClickDelegate = Function.createDelegate(this, this._toolBarOptionItemClick);

				command = new Typps.Command(null/*ToolBarItem will make itself the sender when null*/, this._toolBarOptionItemClickDelegate);
				toolBarItem = this.createToolBarItem(optionName, false, optionsImage, marginLeft, ++j,
                        optionsTitle, true, enableOptions, 0/*Typps.BarItemType.ToolBarItem*/, distance, false, groupName, disabledBackColor, disabledBorderColor, disabledTransparency, command, node);
				toolBarSet.add(toolBarItem);
			}
			this._toolBars.add(toolBarSet, i);
		}
		this._toggleManager.releaseAll();
	},
	_onAutoToggleHandler: function (sender, args) {
		/*special case for td. toggle manager already has a reference if the current element
		clicked is a td or nested in a td element. saves us the trouble of looking for it in the dom again*/
		/*toDo: no need to maintain a globalvariable? just interrogate toggleManager and pull the value from there when needed*/
		this._editableTableCell = sender.get_activeNode('td');
	},
	_tabItemClick: function (sender, args) {
		var name = sender.get_name();
		var arguments = new Typps.EventArgs();
		arguments.set_commandName(name);
		arguments.set_innerArgs(args);

		this._toggleManager.releaseHighlight();
		var applyShade = (name != 'designview');
		this._toolBarShaderShow(applyShade);
		var tabs = this.get_tabs();
		tabs.select(name); //makes this tab the active tab
		var handler = this.get_events().getHandler('tabitemclick');
		if (handler)
			handler(this, arguments);
		this._executeCommand(arguments);
	},
	_toolBarItemClick: function (sender, args) {
		var name = sender.get_name();
		var arguments = new Typps.EventArgs();
		arguments.set_commandName(name);
		arguments.set_innerArgs(args);

		this._toggleManager.releaseHighlight();
		this._toggleManager.selectToolBarItem(name);

		this._lastRange = this.rangeComponent.createRange();
		/*shouldn't we allow the subscriber to cancel execution with a return false instead of an all out out solution like this?*/
		var handler = this.get_events().getHandler('toolbaritemclick');
		if (handler)
			handler(this, arguments);
		this._executeCommand(arguments);
	},
	_toolBarOptionItemClick: function (sender, args) {
		var name = sender.get_name();
		var arguments = new Typps.EventArgs();
		arguments.set_commandName(name);
		arguments.set_innerArgs(args);
		this._toggleManager.releaseHighlight();

		this._lastRange = this.rangeComponent.createRange();

		var handler = this.get_events().getHandler('toolbaroptionitemclick');
		if (handler)
			handler(this, arguments);
		this._executeCommand(arguments);
	},
	createToolBarSet: function (leftBorderImage, optionsName, optionsImage, optionsTitle, element) {
		var mode = this._mode;
		var direction = this._direction;
		var className = this._className;
		return $create(Typps.ToolBarSet,
        {
        	leftBorderImage: leftBorderImage,
        	optionsName: optionsName,
        	optionsImage: optionsImage,
        	optionsTitle: optionsTitle,
        	className: className,
        	mode: mode,
        	direction: direction
        }, null, null, element);
	},
	createTabs: function (leftBorderImage, optionsName, optionsImage, optionsTitle, element) {
		var mode = this._mode;
		var direction = this._direction;
		var className = this._className;
		return $create(Typps.Tabs,
        {
        	leftBorderImage: leftBorderImage,
        	optionsName: optionsName,
        	optionsImage: optionsImage,
        	optionsTitle: optionsTitle,
        	className: className,
        	mode: mode,
        	direction: direction
        }, null, null, element);
	},
	createToolBarItem: function (name, divider, icon, marginLeft, index, title, isOptions, enabled, barItemType, distance, toggleEnabled, groupName, disabledBackColor, disabledBorderColor, disabledTransparency, command, node) {
		var separatorImage = this._toolBarSepratorImage;
		var transparentImage = this._transparentImageUrl;
		var mode = this._mode;
		var direction = this._direction;
		var className = this._className;
		return $create(Typps.ToolBarItem,
        {
        	name: name,
        	divider: divider,
        	icon: icon,
        	marginLeft: marginLeft,
        	index: index,
        	title: title,
        	isOptions: isOptions,
        	enabled: enabled,
        	barItemType: barItemType,
        	distance: distance,
        	separatorImage: separatorImage,
        	transparentImage: transparentImage,
        	className: className,
        	mode: mode,
        	direction: direction,
        	toggleEnabled: toggleEnabled,
        	groupName: groupName,
        	disabledBackColor: disabledBackColor,
        	disabledBorderColor: disabledBorderColor,
        	disabledTransparency: disabledTransparency,
        	command: command
        }, null, null, node);
	},
	createTabItem: function (name, divider, icon, marginLeft, index, title, isOptions, enabled, barItemType, width, distance, selected, disabledBackColor, disabledBorderColor, disabledTransparency, command, node) {
		var separatorImage = this._toolBarSepratorImage;
		var transparentImage = this._transparentImageUrl;
		var mode = this._mode;
		var direction = this._direction;
		var className = this._className;
		return $create(Typps.TabItem,
        {
        	name: name,
        	divider: divider,
        	icon: icon,
        	marginLeft: marginLeft,
        	index: index,
        	title: title,
        	isOptions: isOptions,
        	enabled: enabled,
        	barItemType: barItemType,
        	width: width,
        	distance: distance,
        	separatorImage: separatorImage,
        	transparentImage: transparentImage,
        	className: className,
        	mode: mode,
        	direction: direction,
        	selected: selected,
        	disabledBackColor: disabledBackColor,
        	disabledBorderColor: disabledBorderColor,
        	disabledTransparency: disabledTransparency,
        	command: command
        }, null, null, node);
	},
	_enableToolBarItem: function (name) {
		var enabled = true;
		switch (name) {
			case 'csslist':
				enabled = this._cssListEnabled;
				break;
			case 'spell':
				enabled = this._dictionaryEnabled;
				break;
			case 'cut':
			case 'copy':
			case 'paste':
				if (!this._isIE)
					enabled = false;
				break;
		}
		return enabled;
	},
	_focusFirstChild: function () {
		if (this._isIE) {
			var body = this.iframe.body;
			for (var num1 = 0; num1 < body.childNodes.length; num1++) {
				var elem = body.childNodes[num1];
				if (elem.nodeType == 1) {
					this._maintainSelection(elem);
					try {
						if (this._lastRange.collapse)
							this._lastRange.collapse(true);
						if (this._lastRange.select) {
							this._lastRange.select();
						}
					} catch (exception) { }
					break;
				}
			}
		}
		else {
			/*the fix for caret disappearing act in firefox? \o/
			this bug is most likely related to the special accessibility feature(browsewithcaret) supported in firefox.
			I don't know another fix. this also allows us to keep the document focused in opera/safari/chrome.
			*/
			this.iframeElement.focus();
			this.iframeElement.blur();
			this.iframeElement.focus();
		}
	},
	_dimention: function () {
		if (this._element == null) return;

		var offsetHeight = parseInt(this._height);
		this.iframeElement.style.width = '100%';
		this._designArea.style.width = '100%';
		this._designArea.style.height = 'auto';
		this.iframeElement.style.height = offsetHeight + 'px';
		if (offsetHeight > 0) {
			this._editorText.style.height = offsetHeight + 'px';
			Typps.Utility.setFloat(this._editorText, 'left');
			this._editorText.style.width = '100%';
			this._editorText.style.margin = '0px';
			this._editorText.style.padding = '0px';

			this._nonEditableHtml.style.height = offsetHeight + 'px';
			this._nonEditableHtml.style.width = '100%';

			this._warningsLog.style.height = offsetHeight + 'px';
		}
	},

	_onResizeHandler: function (event) {
		if (!this._enableToolBarFloat) {
			this._toolBarShaderShow(null);
			return false;
		}
		/*fix resize bug in IE6 & IE7 since it fires this event twice,
		once for the body and once for the window. Introducing a delay is
		is the only known workaround.
		Next in IE6 it just goes into a nasty loop so remove/add handler.
		*/
		if (this._isIE && Sys.Browser.version <= 7) {
			Sys.UI.DomEvent.removeHandler(window, 'resize', this._onResizeHandlerDelegate);
			var context = this;
			window.setTimeout(function () {
				context._snapBackFloatingToolBarContainer();
				Sys.UI.DomEvent.addHandler(window, 'resize', context._onResizeHandlerDelegate);
			}, 10);
		}
		else {
			this._snapBackFloatingToolBarContainer();
		}
	},
	_onScrollHandler: function (event) {
		if (!this._enableToolBarFloat) {
			this._toolBarShaderShow(null);
			return false;
		}
		if (this._enableToolBarFloat && (this._isIE && Sys.Browser.version == 6)) {
			var context = this;
			window.setTimeout(function () {
				var floatingContainer = $get(context._id + '_floatingToolBar');
				if (floatingContainer.style.visibility == 'hidden') return;
				var newPosition = Typps.Utility.scrollDistance();
				floatingContainer.style.left = newPosition.x + 'px';
				floatingContainer.style.top = newPosition.y + 'px';
				context._snapBackFloatingToolBarContainer();
			}, 0);
		}
	},
	/*ensure that all block elements are selectable in designview by appending a br element in every empty block element*/
	_fillEmptyBlockElements: function () {
		var elems = this.iframe.body.getElementsByTagName('*');
		var elementsToIgnore = ['ul', 'ol', 'table', 'tr', 'fieldset', 'dl'];
		for (var num1 = 0; num1 < elems.length; num1++) {
			var elem = elems[num1];
			var hasContent = false;
			if (this._isBlockElement(elem)) {
				if (elem.hasChildNodes()) {
					var sibling = elem.firstChild;
					while (sibling) {
						if (sibling.nodeType == 1 || !Typps.Utility.isEmptyTextNode(sibling)) {
							hasContent = true;
							break;
						}
						sibling = sibling.nextSibling;
					}
				}
				if (!hasContent && !Array.contains(elementsToIgnore, elem.nodeName.toLowerCase())) {
					elem.appendChild(this.iframe.createElement('br'));
				}
			}
		}
	},
	_isBlockElement: function (elem) {
		if (elem == null) return false;
		var nodeName = elem.nodeName.toLowerCase();
		var blockLevel = Typps.Utility.getBlockLevelElements();
		var length = blockLevel.length;
		for (var num1 = 0; num1 < length; num1++) {
			var name = blockLevel[num1];
			if (name == nodeName)
				return true;
		}
		return false;
	},
	_iframeBodyClickHandler: function (args) {
		if (this._isOpera) args.stopPropagation();
		if (this._enableToolBarFloat)
			this._displayFloatingToolBar();
		this._ensureLastParagraph();
	},
	_ensureLastParagraph: function () {
		if (this.iframe && this.iframe.body) {
			var lastNode = this.iframe.body.lastChild;
			if (lastNode != null &&
            ((lastNode.nodeType == 1 && (lastNode.nodeName.toLowerCase() != 'p')))
            && lastNode.parentNode.nodeName.toLowerCase() == 'body') {
				var p = this.iframe.createElement('p');
				p.appendChild(this.iframe.createElement('br'));
				this.iframe.body.appendChild(p);
			}
		}
		this._fillEmptyBlockElements();
	},
	_htmlViewInitialize: function () {
		if (this._htmlViewDoubleClickDelegate === null) {
			this._htmlViewDoubleClickDelegate = Function.createDelegate(this, this._htmlViewDoubleClickHandler);
		}
		Sys.UI.DomEvent.addHandler(this._editorText, 'dblclick', this._htmlViewDoubleClickDelegate);

		this._editorText.setAttribute('wrap', 'off');
	},
	_htmlViewDoubleClickHandler: function (event) {
		/*This is a hidden feature. double click in the textarea
		allows you to toggle the wrap mode*/
		var value = this._editorText.getAttribute('wrap');
		this._editorText.setAttribute('wrap', (value == 'off' ? 'soft' : 'off'));
		this._editorText.style.display = 'none';
		var context = this;
		window.setTimeout(function () { context._editorText.style.display = ''; }, 1);
	},
	_makeWebRequest: function (eventArgs, formKeyValuePair) {
		var pageManager = Sys.WebForms.PageRequestManager.getInstance();
		var formBody = Typps.Utility.getFormKeyValuePair(this._uniqueId, formKeyValuePair, this._form, this._postbackAllFormData);
		var request = new Sys.Net.WebRequest();
		request.set_url(this._form.action);
		request.get_headers()['X-MicrosoftAjax'] = 'Delta=true';
		request.get_headers()['Cache-Control'] = 'no-cache';
		request.set_timeout(pageManager._asyncPostBackTimeout);
		request.set_body(formBody);

		if (this._updatePanelProgress === null)
			this._updatePanelProgress = $find(this._updatePanelProgressId);

		this._updatePanelProgress.set_loadingMessage(eventArgs.get_commandArgument());
		if (this._beginRequestHandlerDelegate == null) {
			this._beginRequestHandlerDelegate = Function.createDelegate(this, this._beginRequestHandler);
			this._updatePanelProgress.add_beginRequest(this._beginRequestHandlerDelegate);
		}
		if (this._endRequestHandlerDelegate == null) {
			this._endRequestHandlerDelegate = Function.createDelegate(this, this._endRequestHandler);
			this._updatePanelProgress.add_endRequest(this._endRequestHandlerDelegate);
		}
		this._updatePanelProgress._makeWebRequest(request);
	},

	_iframeDefaults: function () {
		var direction = (this._direction == Typps.Editor.Dir.LTR) ? 'ltr' : 'rtl';
		var cssText = this._initializeCssStyle();
		if (cssText != '') {
			var ss = this.iframe.createElement('style');
			ss.setAttribute('type', 'text/css');
			if (ss.styleSheet) {
				ss.styleSheet.cssText = cssText;
			}
			else {
				var tn = this.iframe.createTextNode(cssText);
				ss.appendChild(tn);
			}
			this.iframe.getElementsByTagName('head')[0].appendChild(ss);
		}
		this.iframe.getElementsByTagName('html')[0].style.borderStyle = 'none';
		this.iframe.getElementsByTagName('html')[0].className = String.format('{0}-iframehtmlstyle', this._className);
		this.iframe.body.className = String.format('{0}-htmlelementlabels', this._className);
		if (this._autoSwitchTextDirection)
			this.iframe.body.dir = direction;

		Typps.Utility.setDesignMode(this.iframe, true);
	},
	_paragraphWrappedInnerHTML: function (html) {
		var div = document.createElement('div');
		if (!Typps.Utility.isNullOrEmpty(html)) {
			html = this.tokenizeUrls(Typps.Perform.Add, html);
			div = Typps.Utility.getAdjacentHTML(html, div);
			var list = null;
			var node = null;
			for (var num1 = 0; num1 < div.childNodes.length; num1++) {
				node = div.childNodes[num1];
				if (Typps.Utility.isEmptyTextNode(node))
					continue;
				if (list == null)
					list = [];
				Array.add(list, node);
			}
			if (list != null) {
				var p = null;
				var blockElements = Typps.Utility.getBlockLevelElements();
				for (var index1 in list) {
					node = list[index1];
					if (node.nodeType == 1) {
						var nodeName = node.nodeName.toLowerCase();
						var flag1 = false;
						for (var index2 in blockElements) {
							var blockElement = blockElements[index2];
							if (nodeName == blockElement) {
								p = null;
								flag1 = true;
								break;
							}
						}
						if (flag1) continue;
					}
					if (p == null) {
						p = document.createElement('p');
						div.insertBefore(p, node);
						p.appendChild(div.removeChild(node));
					} else {
						p.appendChild(div.removeChild(node));
					}
				}
			}
		}
		else {
			p = document.createElement('p');
			p.appendChild(document.createElement('br'));
			div.appendChild(p);
		}
		return this.tokenizeUrls(Typps.Perform.Remove, div.innerHTML);
	},
	_getNodeBeforeCursor: function () {
		if (this._isIE) return null;
		var sel = this.contentWindow.getSelection();
		var range = sel.getRangeAt(0);
		var container = range.endContainer;
		var nodeBeforeCursor = null;
		for (var num1 = 0; num1 < container.childNodes.length; num1++) {
			var node = container.childNodes[num1];
			//-1 means node is before the current position
			if (range.comparePoint(node, 0) == -1)
				nodeBeforeCursor = node;
		}
		return (nodeBeforeCursor == null) ? container : nodeBeforeCursor;
	},
	_initializeCssStyle: function () {
		/* get a reference to the parent documents stylesheets collection */
		var embededStyleText = '';
		if (this._externalStyleSheet != '') {
			//if this editor is being loaded for the first time due to an async
			//callback, then let's attempt to add the link
			//but first let's verify the style has not been added.
			if (!this._isExistStyleSheet(this._externalStyleSheet,
                        document.styleSheets)) {
				this._addStyleSheetLink(document, this._externalStyleSheet);
			}
			if (!this._isExistStyleSheet(this._externalStyleSheet,
                        this.iframe.styleSheets)) {
				this._addStyleSheetLink(this.iframe, this._externalStyleSheet);
			}
		}
		else {
			embededStyleText = this._getCssFromStyleSheets(document.styleSheets);
		}
		var references = this._externalStyleSheetReferences.split(',');
		var num1 = 0;
		for (num1 = 0; num1 < references.length; num1++) {
			var reference = references[num1];
			if (reference != '') {
				if (!this._isExistStyleSheet(reference,
                        this.iframe.styleSheets))
					this._addStyleSheetLink(this.iframe, reference);
			}
		}
		//add the external stylesheets to your embeded object tag document too.
		//these are the custom css styles displayed via the editor dropdown
		if (this._externalStyleSheets != '') {
			var styleSheets = this._externalStyleSheets.split(',');
			for (num1 = 0; num1 < styleSheets.length; num1++) {
				var ss1 = styleSheets[num1];
				for (var num2 = 0; num2 < document.styleSheets.length; num2++) {
					var ss2 = document.styleSheets[num2];
					if (ss2.href != null &&
                     ss2.href.toLowerCase().indexOf(ss1.toLowerCase()) != -1) {
						this._addStyleSheetLink(this.iframe, ss2.href);
						break;
					}
				}
			}
		}
		return embededStyleText;
	},
	_addStyleSheetLink: function (doc, href) {
		if (href == null || href == '') return;
		var styleSheetLink = doc.createElement('link');
		styleSheetLink.setAttribute('type', 'text/css');
		styleSheetLink.setAttribute('href', href);
		styleSheetLink.setAttribute('rel', 'stylesheet');
		doc.getElementsByTagName('head')[0].appendChild(styleSheetLink);
	},
	_isExistStyleSheet: function (name, styleSheets) {
		for (var num1 = 0; num1 < styleSheets.length; num1++) {
			var styleSheet = styleSheets[num1];
			var href = styleSheet.href;
			if (href != null) {
				var start = name.lastIndexOf('/');
				if (start != -1)
					name = name.substring(start + 1, name.length);
				start = href.lastIndexOf('/');
				if (start != -1)
					href = href.substring(start + 1, href.length);
				else
					href = href;
				if (href.toLowerCase() == name.toLowerCase())
					return true;
			}
		}
		return false;
	},
	_getCssFromStyleSheets: function (styleSheets) {
		var cssText = new Sys.StringBuilder();
		var classIdentifiers = this._cssClassIdentifiers.split(',');
		if (classIdentifiers.length > 0) {
			for (var num1 = 0; num1 < styleSheets.length; num1++) {
				var style = styleSheets[num1];
				for (var num2 = 0; num2 < classIdentifiers.length; num2++) {
					try {
						var fileName = classIdentifiers[num2].toLowerCase();
						var rules = (this._isIE) ? style.rules : style.cssRules;
						if (rules.length > 0) {
							var rule = rules[0];
							if ((rule.selectorText != undefined &&
                            rule.selectorText.toLowerCase().indexOf(fileName) != -1))
								if (this._isIE)
									cssText.append(style.cssText);
								else
									cssText.append(this._getCssRulesText(rules));
						}
					}
					catch (exception) {
						//NS_ERROR_DOM_SECURITY_ERR when trying to access cssRules from a stylesheet cross domain.
						//make sure stylesheet references aren't referenced cross domain
						//gnam gnam lets supress it
					}
				}
			}
		}
		return cssText.toString();
	},
	_getCssRulesText: function (cssRules) {
		/*read out cssRules one by one and build the entire css contained in our cssRules collection*/
		var cssText = new Sys.StringBuilder();
		for (var num1 = 0; num1 < cssRules.length; num1++) {
			cssText.append(cssRules[num1].selectorText + '{' + cssRules[num1].style.cssText + '}');
		}
		return cssText.toString();
	},

	_beginRequestHandler: function (sender, args) {
		var h = this.get_events().getHandler('beginWebRequest');
		if (h) h(this, args);
	},
	_endRequestHandler: function (sender, args) {
		var h = this.get_events().getHandler('endWebRequest');
		if (!sender.get_responseAvailable()) {
			if (h) h(this, args);
			return;
		}
		var id = this.get_id();
		var eventArgs = new Typps.EventArgs();
		var parts = sender.get_responseData().split(String.format('$callbackdata${0}$sep$', id));
		var key = parts[0];
		var value = parts[1];
		eventArgs.set_commandName(key);
		eventArgs.set_commandArgument(value);
		eventArgs.set_innerArgs(args);
		if (h) h(this, eventArgs);

		switch (key) {
			case 'TableDesignerRequest':
				this._createTableDesigner(value);
				break;
			case 'CellsDesignerRequest':
				this._createCellsDesigner(value);
				break;
			case 'HyperlinkRequest':
				this._createHyperlink(value);
				break;
			case 'CodeHighlighterRequest':
				this._createCodeHighlighter(value);
				break;
			case 'CodeHighlighting':
				this._addCodeHighlight(value);
				break;
			case 'WordPasteCleanupRequest':
				this._createWordPasteCleanup(value);
				break;
			case 'SpellCheckerRequest':
				this._createSpellChecker(value);
				break;
			case 'SelectedDictionary':
				this._processSpellCheckResponse(value);
				break;
			case 'WordSuggestionRequest':
				this._wordSuggestion(value);
				break;
			case 'WordPastingCleanup':
				this._addWordPastingCleanedUp(value);
				break;
			case 'CssClassNamesListRequest':
				this._createCssClassNamesList(Sys.Serialization.JavaScriptSerializer.deserialize(value));
				break;
			case 'ValidationRequest':
				this._createHtmlViewAfterValidation(value);
				break;
			case 'DesignViewValidationRequest':
				this._createDesignViewAfterValidation(value);
				break;
			case 'HtmlViewHighlightRequest':
				this._createHtmlViewHighlight(value);
				break;
			case 'MultiFileUploaderRequest':
				this._createMultiFileUploader(value);
				break;
			case 'FileBrowserRequest':
				this._createFileBrowser(value);
				break;
			case 'FileUploadRequest':
				this._createFileUploader(value);
				break;
			case 'Save':
				h = this.get_events().getHandler('saved');
				value = Sys.Serialization.JavaScriptSerializer.deserialize(value);
				eventArgs.set_commandArgument(value.messageFromServer);
				if (h) h(this, eventArgs);
				break;
		}
	},
	_getIframe: function (id, container, display) {
		var iframe = $get(id);
		if (iframe != null) return iframe;
		var ieBelow9 = this._isIE && Sys.Browser.version < 9;
		if (ieBelow9) {
			iframe = document.createElement(String.format('<iframe name="{0}">', id));
		}
		else {
			iframe = document.createElement('iframe');
			iframe.name = id;
		}
		iframe.id = id;
		if (display) {
			if (!ieBelow9)
				iframe.src = this._dataFileUrl;
			iframe.className = this._className + '-frame';
			iframe.style.margin = '0px';
			iframe.style.padding = '0px';
			iframe.style.borderWidth = '0px';
			iframe.style.borderStyle = 'none';
			iframe.style.zIndex = '-1';
			Typps.Utility.setFloat(iframe, 'left');
		}
		else {
			iframe.style.display = 'none';
		}
		container.appendChild(iframe);
		return iframe;
	},
	_multiFileUploader: function () {
		var argument = Typps.Utility.getCommandArgument('multifileuploader', this.get_callbacks());
		var formKeyValuePair = { formdata: argument.commandArgument };
		if (this._multiFileUploaderWindow == null) {
			this._fireUpdatePanelTrigger(formKeyValuePair, argument.commandArgument, argument.message);
		} else {
			this._multiFileUploaderFill();
			this._multiFileUploaderWindow.show(true);
		}
	},
	_createMultiFileUploader: function (markup) {
		var container = document.createElement('div');
		this._multiFileUploaderWindow = this._createModalPopup(markup, this._multiFileUploaderId, true);
		if (this._btnMultiFileUploaderOkDelegate === null)
			this._btnMultiFileUploaderOkDelegate = Function.createDelegate(this, this._btnMultiFileUploaderOkHandler);
		if (this._btnMultiFileUploaderCancelDelegate === null)
			this._btnMultiFileUploaderCancelDelegate = Function.createDelegate(this, this._btnMultiFileUploaderCancelHandler);
		if (this._btnMultiFileUploaderAddNewDelegate === null)
			this._btnMultiFileUploaderAddNewDelegate = Function.createDelegate(this, this._btnMultiFileUploaderAddNewHandler);
		var btnAddNew = $get(this._multiFileUploaderId + '_btnaddnew');
		if (btnAddNew != null)
			Sys.UI.DomEvent.addHandler(btnAddNew, 'click', this._btnMultiFileUploaderAddNewDelegate);
		this._multiFileUploaderWindow.add_okButton(this._btnMultiFileUploaderOkDelegate);
		this._multiFileUploaderWindow.add_cancelButton(this._btnMultiFileUploaderCancelDelegate);
		this._multiFileUploaderWindow.add_popupCloseButton(this._btnMultiFileUploaderCancelDelegate);
		this._multiFileUploaderFill();
	},
	_btnMultiFileUploaderAddNewHandler: function (args) {
		var elem = args.target;
		this._addNewFileInput();
	},
	_addNewFileInput: function () {
		var multiFileUploaderList = $get(this._multiFileUploaderId + '_list');
		var li = document.createElement('li');
		var input = document.createElement('input');
		input.id = String.format('{0}_{1}', this._multiFileUploaderId, ++this._lastMultiFileInputIndex);
		input.type = 'file';
		input.name = input.id;
		if (this._multiFileUploadMimeFilter != '')
			input.setAttribute('accept', this._multiFileUploadMimeFilter);
		li.appendChild(input);
		this._addFileInputRemoveButton(li, input.id + '_remove');
		multiFileUploaderList.appendChild(li);
	},
	_btnMultiFileUploaderOkHandler: function (args) {
		var iframe = this._getIframe(this._multiFileUploaderId + '_iframe', this._form, false);
		var multiFileUploaderList = $get(this._multiFileUploaderId + '_list');
		var list = multiFileUploaderList.getElementsByTagName('li');
		if (this._iframeMultiFileUploadLoadDelegate === null) {
			this._iframeMultiFileUploadLoadDelegate = Function.createDelegate(this, this._iframeMultiFileUploadLoadHandler);
			Sys.UI.DomEvent.addHandler(iframe, 'load', this._iframeMultiFileUploadLoadDelegate);
		}
		var dataList = new Array();
		for (var num1 = 0; num1 < list.length; num1++) {
			var input = list[num1].getElementsByTagName('input')[0];
			var fullPath = input.getAttribute('fullpath');
			var value = 'empty';
			if (fullPath != null || fullPath != undefined)
				value = fullPath;
			Array.add(dataList, { id: input.id, clientSidePath: value });
		}
		var target = this._form.target;
		this._form.target = iframe.name;
		this._form.__EVENTTARGET.value = this._multiFileUploaderId;
		this._form.__EVENTARGUMENT.value = Sys.Serialization.JavaScriptSerializer.serialize(dataList);

		var eventArgs = new Typps.EventArgs();
		eventArgs.set_commandArgument(this._multiFileUploaderProgress);

		if (this._updatePanelProgress === null)
			this._updatePanelProgress = $find(this._updatePanelProgressId);

		this._updatePanelProgress.set_loadingMessage(this._multiFileUploaderProgress);
		this._updatePanelProgress.showProgressBar();

		this._beginRequestHandler(this, eventArgs);

		this._form.submit();
		this._form.target = target;
		this._form.__EVENTTARGET.value = '';
		this._form.__EVENTARGUMENT.value = '';

		this._clearMultiFileUpload();
	},
	_clearMultiFileUpload: function () {
		var multiFileUploaderList = $get(this._multiFileUploaderId + '_list');
		var list = multiFileUploaderList.getElementsByTagName('li');
		var length = list.length - 1;
		//when deleting do it in reverse order or
		//the position of the list changes.
		for (var num1 = length; num1 >= 0; num1--) {
			var node = list[num1];
			var image = $get(String.format('{0}_{1}_remove', this._multiFileUploaderId, num1));
			if (this._multiFileRemoveInputDelegate && image != null)
				Sys.UI.DomEvent.removeHandler(image, 'click', this._multiFileRemoveInputDelegate);
			node.parentNode.removeChild(node);
		}
	},
	_btnMultiFileUploaderCancelHandler: function (args) {
		this._clearMultiFileUpload();
		if (this._multiFileActivation == 0) {
			var args2 = new Typps.EventArgs();
			var html = this.get_htmlText();
			if (this._currentTabView == 0) {
				args2.set_commandName('htmlview');
			} else {
				args2.set_commandName('designview');
				if (!this._isHtmlDirty) {
					this._setDesignViewMode(this.get_htmlText());
					return;
				}
			}
			this._requestHtml(args2, html);
		}
	},
	_iframeMultiFileUploadLoadHandler: function (args) {
		if (this._updatePanelProgress !== null)
			this._updatePanelProgress.hideProgressBar();
		if (this._multiFileActivation == 0 && this._currentTabView == 1)//ah!htmlview,so update it
			this.set_htmlText(this._editorText.value);
		var response = Sys.Serialization.JavaScriptSerializer.deserialize(args.target.contentWindow.document.body.firstChild.innerHTML);
		var elements = this._getElementsByFileSystemPath();
		if (elements.length == 0) return;
		var num1;
		for (num1 = 0; num1 < elements.length; num1++) {
			var elem = elements[num1];
			var nodeName = elem.nodeName.toLowerCase();
			var src = (nodeName == 'a') ? elem.href : elem.src;
			for (var r in response) {
				var o = response[r];
				if (o.clientSideFilePath == src) {
					if (nodeName == 'a') {
						elem.href = o.serverSideFilePath;
						if (this._isIE)
							elem.setAttribute('href2', o.serverSideFilePath);
					} else {
						elem.src = o.serverSideFilePath;
						if (this._isIE)
							elem.setAttribute('src2', o.serverSideFilePath);
					}
					Array.remove(response, o);
					break;
				}
			}
		}
		if (this._multiFileActivation == 0) {
			var args2 = new Typps.EventArgs();
			var html = this.get_htmlText();
			if (this._currentTabView == 0) {
				args2.set_commandName('htmlview');
			} else {
				args2.set_commandName('designview');
				if (!this._isHtmlDirty) {
					this._setDesignViewMode(this.get_htmlText());
					return;
				}
			}
			this._requestHtml(args2, html);
		}
	},
	_multiFileUploaderFill: function () {
		var elements = this._getElementsByFileSystemPath();
		if (elements.length == 0) {
			this._addNewFileInput();
			return;
		}
		var num1;
		var btnAddNew = $get(this._multiFileUploaderId + '_btnaddnew');
		var multiFileUploaderList = $get(this._multiFileUploaderId + '_list');
		for (num1 = 0; num1 < elements.length; num1++) {
			var o = elements[num1];
			var src = (o.nodeName.toLowerCase() == 'a') ? o.href : o.src;
			var li = document.createElement('li');
			var message = String.format(this._fileUploadRequiredMessage, src);
			var input = document.createElement('input');
			input.id = String.format('{0}_{1}', this._multiFileUploaderId, ++this._lastMultiFileInputIndex);
			input.type = 'file';
			input.name = input.id;
			if (this._multiFileUploadMimeFilter != '')
				input.setAttribute('accept', this._multiFileUploadMimeFilter);
			input.setAttribute('fullpath', src);
			li.appendChild(input);
			this._addFileInputRemoveButton(li, input.id + '_remove');
			li.appendChild(document.createElement('br'));
			li.appendChild(document.createTextNode(message));
			multiFileUploaderList.appendChild(li);
		}
	},
	_addFileInputRemoveButton: function (container, id) {
		if (this._fileRemoveImageUrl != null || this._fileRemoveImageUrl != '') {
			var image = document.createElement('img');
			image.id = id;
			image.src = this._fileRemoveImageUrl;
			if (this._multiFileRemoveInputDelegate === null)
				this._multiFileRemoveInputDelegate = Function.createDelegate(this, this._multiFileRemoveInputHandler);
			Sys.UI.DomEvent.addHandler(image, 'click', this._multiFileRemoveInputDelegate);
			container.appendChild(image);
		}
	},
	_multiFileRemoveInputHandler: function (args) {
		var elem = args.target;
		var li = elem.parentNode;
		li.parentNode.removeChild(li);
		if (this._multiFileRemoveInputDelegate)
			Sys.UI.DomEvent.removeHandler(elem, 'click', this._multiFileRemoveInputDelegate);
	},
	_mergeArrayFromHtmlCollection: function (array1, htmlCollection) {
		if (htmlCollection == null || htmlCollection.length == 0) return array1;
		for (var num1 = 0; num1 < htmlCollection.length; num1++)
			array1[array1.length] = htmlCollection[num1];
		return array1;
	},
	_hasLocalFilePath: function () {
		return (this._getElementsByFileSystemPath().length > 0);
	},
	_getElementsByFileSystemPath: function () {
		var allElements = new Array();
		var elements = new Array();
		var array1 = this.iframe.getElementsByTagName('img');
		var array2 = this.iframe.getElementsByTagName('a');
		allElements = this._mergeArrayFromHtmlCollection(allElements, array1);
		allElements = this._mergeArrayFromHtmlCollection(allElements, array2);
		var num1;
		for (num1 = 0; num1 < allElements.length; num1++) {
			var o = allElements[num1];
			var src = (o.nodeName.toLowerCase() == 'a') ? o.href : o.src;

			if (src.startsWith('file:'))
				Array.add(elements, o);
		}
		return elements;
	},
	_createHtmlViewHighlight: function (markup) {
		this.iframeElement.style.display = 'none';
		this._warningsLog.style.display = 'none';
		this._editorText.style.display = 'none';
		this._nonEditableHtml.innerHTML = markup;
		this._nonEditableHtml.style.display = '';
		this._currentTabView = Typps.Editor.TabView.HtmlViewColored;
	},
	_createHtmlViewAfterValidation: function (markup) {
		var pair = markup.split('$Html$ErrorLog$Sep$');
		var validatedMarkup = pair[0];
		var errorLog = pair[1];
		var errorLogMessageDialog = pair[2];
		this._warningsLog.innerHTML = errorLog;
		this._editorText.value = validatedMarkup;
		this.iframeElement.style.display = 'none';
		this._warningsLog.style.display = 'none';
		this._nonEditableHtml.style.display = 'none';
		this._editorText.style.display = '';
		if (errorLogMessageDialog != null && errorLogMessageDialog.length > 0)
			this._createErrorLogMessageDialog(errorLogMessageDialog);
		this._currentTabView = Typps.Editor.TabView.HtmlView;
	},
	_createDesignViewAfterValidation: function (markup) {
		var pair = markup.split('$Html$ErrorLog$Sep$');
		var validatedMarkup = pair[0];
		var errorLog = pair[1];
		var errorLogMessageDialog = pair[2];
		this._warningsLog.innerHTML = errorLog;
		this._setDesignViewMode(validatedMarkup);
		if (errorLogMessageDialog != null && errorLogMessageDialog.length > 0)
			this._createErrorLogMessageDialog(errorLogMessageDialog);
		this._currentTabView = Typps.Editor.TabView.DesignView;
	},
	_createErrorLogMessageDialog: function (markup) {
		//this._blinkTabByCommandName('warninglog');
		if (this._displayErrorLogMessage && this._errorsLoggedMessagePopup == null) {
			var container = document.createElement('div');
			var content = Typps.Utility.getAdjacentHTML(markup, container).firstChild;
			var id = this.get_id() + '_errorsloggedmessage';
			var ok = id + '_btnok';
			this._errorsLoggedMessagePopup = $create(Typps.ModalPopup,
            { id: id, display: true, content: content, title: content.title, isModal: true, className: this._className, shaderColor: this._shaderColor, shaderOpacity: this._shaderOpacity, okButtonId: ok, formElementId: this._formElementId },
            null, null, null);
			if (this._warningsLogMessageOkDelegate === null) {
				this._warningsLogMessageOkDelegate = Function.createDelegate(this, this._warningsLogMessageOkHandler);
				this._errorsLoggedMessagePopup.add_okButton(this._warningsLogMessageOkDelegate);
			}
			var btnErrorLog = $get(id + '_btnerrorlog');
			if (this._warningsLogShowDelegate === null) {
				this._warningsLogShowDelegate = Function.createDelegate(this, this._warningsLogShowHandler);
				Sys.UI.DomEvent.addHandler(btnErrorLog, 'click', this._warningsLogShowDelegate);
			}
		}
		else if (this._displayErrorLogMessage && this._errorsLoggedMessagePopup != null) {
			this._errorsLoggedMessagePopup.show(true);
		}
		else if (!this._displayErrorLogMessage && this._errorsLoggedMessagePopup != null) {
			this._errorsLoggedMessagePopup.remove_okButton(this._warningsLogMessageOkDelegate);
			this._errorsLoggedMessagePopup.dispose();
		}
		this._toolBarShaderShow(null);
	},
	_warningsLogShowHandler: function (event) {
		var id = this.get_id();
		var display = $get(id + '_errorsloggedmessage_showagain');
		this._displayErrorLogMessage = !display.checked;
		var args = new Typps.EventArgs();
		this._errorsLoggedMessagePopup.show(false);
		this._warningLog(args);
		this._currentTabView = Typps.Editor.TabView.WarningLog;
	},
	_warningsLogMessageOkHandler: function (event) {
		var id = this.get_id();
		var display = $get(id + '_errorsloggedmessage_showagain');
		this._displayErrorLogMessage = !display.checked;
	},
	_createCssClassNamesList: function (cssClassNamesCollection) {
		if (this._cssClassNamesList === null) {
			var id = this.get_id() + '_dropdownclassnamelist';
			var commandName = 'csslist';

			var cssListToolBarItem = this._toolBars.getToolBarItem(commandName);
			var title = cssListToolBarItem.get_title();
			var targetControl = cssListToolBarItem.get_element();

			var listItemClassName = this._className + '-dropdownclassnamelist';

			var list = [];
			for (var index in cssClassNamesCollection) {
				var item = cssClassNamesCollection[index];
				Array.add(list, { text: item.className, value: item.value, toolTip: item.toolTip });
			}

			var options = this._createDropDownListOptions(listItemClassName, title, commandName, targetControl, list, null, null, true, null);
			this._cssClassNamesList = this._createDropDownList(id, options);
			if (this._ddlCssClassNamesListSelectDelegate === null)
				this._ddlCssClassNamesListSelectDelegate = Function.createDelegate(this, this._ddlCssClassNamesListSelectHandler);
			this._cssClassNamesList.add_listItemSelected(this._ddlCssClassNamesListSelectDelegate);

			if (this._ddlCssClassNamesListCloseDelegate === null)
				this._ddlCssClassNamesListCloseDelegate = Function.createDelegate(this, this._ddlCssClassNamesListCloseHandler);

			this._cssClassNamesList.add_close(this._ddlCssClassNamesListCloseDelegate);
		}
		this._cssClassNamesList.show();
	},
	_ddlCssClassNamesListSelectHandler: function (sender, args) {
		var className = args.get_selectedValue();

		var selectedItem = this.rangeComponent.getAllNodesInRange(this._lastRange);
		var nodes = selectedItem.get_nodes();
		var hasSelection = selectedItem.get_hasSelection();

		var num1 = 0;
		var node = null;
		var nodeName = null;

		var length = nodes.length - 1;
		for (num1 = length; num1 >= 0; num1--) {
			node = nodes[num1];
			if (Typps.Utility.isBr(node)) {
				var alternateNode = node.previousSibling;
				if (alternateNode != null && !Array.contains(nodes, alternateNode))
					Array.insert(nodes, num1, alternateNode);
				Array.remove(nodes, node);
			}
		}
		var distinctNodes = this.rangeComponent.selectDistinctNodes(nodes);
		distinctNodes = this._getAncestorNodes(distinctNodes, !hasSelection);
		length = distinctNodes.length;
		if (length == 0) return;

		for (num1 = 0; num1 < length; num1++) {
			node = distinctNodes[num1];
			if (node.nodeType == 1) {
				this._toggleCssClass(node, className);
			} else if (node.nodeType == 3) {
				var span = this.iframe.createElement('span');
				node = node.parentNode.replaceChild(span, node);
				span.appendChild(node);
				this._toggleCssClass(span, className);
			}
		}
		this.rangeComponent.selectAll(nodes);
	},
	_getAncestorNodes: function (nodes, replaceTextNode) {
		//second pass, ensure that if a node
		//has no siblings, then replace with it's parent
		var length = nodes.length - 1;
		for (var num1 = length; num1 >= 0; num1--) {
			node = nodes[num1];
			if (node.nodeType == 1) continue;
			parentNode = node.parentNode;
			var flag1 = true;
			while (parentNode) {
				nodeName = parentNode.nodeName.toLowerCase();
				if (nodeName == 'body') break;
				if (Array.contains(nodes, parentNode)) {
					flag1 = false;
					break;
				}
				parentNode = parentNode.parentNode;
			}

			if (flag1) {
				parentNode = node.parentNode;
				var sibling = parentNode.firstChild;
				var flag2 = true;
				while (sibling) {
					if (((sibling != node && !Typps.Utility.isBr(sibling)) &&
                            !Array.contains(nodes, sibling)) && !Typps.Utility.isEmptyTextNode(sibling)) {
						flag2 = false;
						break;
					}
					sibling = sibling.nextSibling;
				}
				if ((flag2 || replaceTextNode) || Typps.Utility.isEmptyTextNode(node)) {
					if (!Array.contains(nodes, parentNode))
						Array.insert(nodes, num1, parentNode);
					Array.remove(nodes, node);
				}
			}
			else {
				//an ancestor is already present
				Array.remove(nodes, node);
			}
		}
		return nodes;
	},
	_ddlCssClassNamesListCloseHandler: function (sender, args)
	{ },
	_wordSuggestion: function (markup) {
		if (this._dictionaryDropDownListCollection === null)
			this._dictionaryDropDownListCollection = [];
		var index = this._dictionaryDropDownListCollection.length;
		var wordPair = markup.split('$word$suggestion$sep$');
		var suggestions = wordPair[0] == "" ? null : wordPair[0].split(';');
		var id = wordPair[1] + '_ddl';
		var targetControl = this.iframe.getElementById(wordPair[1]);
		if (targetControl == null)
			return;

		var listItemClassName = this._className + '-dropdownspellsuggestion';

		var list = [];
		if (suggestions != null) {
			var length = suggestions.length - 1;
			for (var num1 = length; num1 >= 0; num1--) {
				var suggestion = suggestions[num1];
				Array.add(list, { text: suggestion, value: null, toolTip: suggestion, attributes: [{ key: 'class', value: listItemClassName + '_menu'}] });
			}
		}
		var menuList = [];
		Array.add(menuList, { text: this._ignoreLabel, value: 'ignore', toolTip: this._ignoreLabel, attributes: [{ key: 'class', value: listItemClassName + '_menu'}] });
		var commandName = 'wordsuggestion';
		var options = this._createDropDownListOptions(listItemClassName, this._suggestionListHeaderTitle, commandName, targetControl, list, menuList, this.iframeElement, false, null);
		var ddl = this._createDropDownList(id, options);

		if (this._ddlMisspellWordSelectDelegate === null && this._ddlMisspellWordCloseDelegate === null) {
			if (this._ddlMisspellWordSelectDelegate === null)
				this._ddlMisspellWordSelectDelegate = Function.createDelegate(this, this._ddlMisspellWordSelectHandler);
			if (this._ddlMisspellWordCloseDelegate === null)
				this._ddlMisspellWordCloseDelegate = Function.createDelegate(this, this._ddlMisspellWordCloseHandler);
			if (this._ddlMisspellWordMenuSelectedDelegate === null)
				this._ddlMisspellWordMenuSelectedDelegate = Function.createDelegate(this, this._ddlMisspellWordMenuSelectedHandler);
		}
		ddl.add_listItemSelected(this._ddlMisspellWordSelectDelegate);
		ddl.add_menuItemSelected(this._ddlMisspellWordMenuSelectedDelegate);
		ddl.add_close(this._ddlMisspellWordCloseDelegate);
		ddl.show();
		this._dictionaryDropDownListCollection[index] = ddl;
	},
	_getSuggestionDropDownListByID: function (id) {
		if (this._dictionaryDropDownListCollection === null) return null;
		for (var num1 = 0; num1 < this._dictionaryDropDownListCollection.length; num1++) {
			var ddl = this._dictionaryDropDownListCollection[num1];
			if (ddl != null && ddl.get_id() == id)
				return ddl;
		}
		return null;
	},
	_disposeSuggestionDropDownList: function (id) {
		if (this._dictionaryDropDownListCollection == null) return;
		var length = this._dictionaryDropDownListCollection.length - 1;
		//when deleting do it in reverse order or 
		//the position of the list changes.
		for (var num1 = length; num1 >= 0; num1--) {
			var ddl = this._dictionaryDropDownListCollection[num1];
			if (ddl != null &&
            (ddl.get_id() == id || id == null)) {
				ddl.dispose();
				Array.remove(this._dictionaryDropDownListCollection, ddl);
			}
		}
		if (id == null) {
			this._dictionaryDropDownListCollection = null;
			this._ddlMisspellWordSelectDelegate = null;
			this._ddlMisspellWordCloseDelegate = null;
		}
	},
	_ddlMisspellWordMenuSelectedHandler: function (sender, args) {
		/*spellchecker dropdownlist contains a command menu --currently supported command is ignore*/
		var wordContainer = sender.get_targetControl();
		var word = wordContainer.innerHTML;
		var value = args.get_selectedValue();
		var id = wordContainer.id + '_ddl';
		Sys.UI.DomEvent.removeHandler(wordContainer, 'mouseup', this._misspellWordClickDelegate);
		switch (value.toLowerCase()) {
			case 'ignore':
				var ignoreWordsStore = $get(this.get_id() + '_ignorewords');
				ignoreWordsStore.value += word + '|';
				wordContainer.parentNode.replaceChild(this.iframe.createTextNode(word), wordContainer);
				break;
		}
	},
	_ddlMisspellWordSelectHandler: function (sender, args) {
		var wordContainer = sender.get_targetControl();
		var word = args.get_selectedValue();
		var id = wordContainer.id + '_ddl';
		Sys.UI.DomEvent.removeHandler(wordContainer, 'mouseup', this._misspellWordClickDelegate);
		wordContainer.parentNode.replaceChild(this.iframe.createTextNode(word), wordContainer);
	},
	_ddlMisspellWordCloseHandler: function (sender, args) {
		var wordContainer = sender.get_targetControl();
		var id = wordContainer.id + '_ddl';
		this._disposeSuggestionDropDownList(id);
	},
	_processSpellCheckResponse: function (markup) {
		var parts = markup.split('$spell$checker$complete$sep$');
		var html = parts[0];
		var spellCheckerTemplate = parts[1];
		var correctionCount = parseInt(parts[2]);
		if (correctionCount > 0 && html.trim() != '')
			this.set_htmlText(html);
		else
			return;
		this._misspellWordsWireEvents();

		var displaySpellingCompleteMessage = this._displaySpellingCompleteMessage;
		var spellCheckerCompleteMessagePopup = this._spellCheckerCompleteMessagePopup;

		if ((displaySpellingCompleteMessage && spellCheckerCompleteMessagePopup == null) && spellCheckerTemplate) {
			var container = document.createElement('div');
			var content = Typps.Utility.getAdjacentHTML(spellCheckerTemplate, container).firstChild;
			var id = this.get_id() + '_spellcheckermessage';
			var ok = id + '_btnok';
			this._spellCheckerCompleteMessagePopup = $create(Typps.ModalPopup,
            { id: id, display: true, content: content, title: content.title, isModal: true, className: this._className, shaderColor: this._shaderColor, shaderOpacity: this._shaderOpacity, okButtonId: ok, formElementId: this._formElementId },
            null, null, null);
			spellCheckerCompleteMessagePopup = this._spellCheckerCompleteMessagePopup;
			spellCheckerCompleteMessagePopup.add_okButton(this._spellCheckerCompleteMessageOkDelegate);
		}
		else if ((displaySpellingCompleteMessage && spellCheckerCompleteMessagePopup != null) && correctionCount > 0) {
			spellCheckerCompleteMessagePopup.show(true);
		}
		else if (!displaySpellingCompleteMessage && spellCheckerCompleteMessagePopup != null) {
			spellCheckerCompleteMessagePopup.remove_okButton(this._spellCheckerCompleteMessageOkDelegate);
			spellCheckerCompleteMessagePopup.dispose();
		}

	},
	_spellCheckerCompleteMessageOkHandler: function (event) {
		var showAgain = $get(this.get_id() + '_spellcheckermessage_showagain');
		this._displaySpellingCompleteMessage = !showAgain.checked;
	},
	_misspellWordsWireEvents: function () {
		var boldElements = this.iframe.getElementsByTagName('b');
		var misspelled = new Array();
		for (var num1 = 0; num1 < boldElements.length; num1++) {
			var bold = boldElements[num1];
			var containsClass = Typps.Utility.containsCssClass(bold, this._className + '-misspelledword');
			if (containsClass) {
				if (this._misspellWordClickDelegate === null) {
					this._misspellWordClickDelegate = Function.createDelegate(this, this._misspellWordClickHandler);
				}
				Sys.UI.DomEvent.addHandler(bold, 'mouseup', this._misspellWordClickDelegate);
			}
		}
		if (this._spellCheckerCompleteMessageOkDelegate === null) {
			this._spellCheckerCompleteMessageOkDelegate = Function.createDelegate(this, this._spellCheckerCompleteMessageOkHandler);
		}
	},
	_misspellWordClickHandler: function (event) {
		if (event.button == 2) return false;
		var id = event.target.id + '_ddl';
		var ddl = this._getSuggestionDropDownListByID(id);
		if (ddl != null) {
			ddl.show();
			return;
		} // otherwise, this is first time, make ajax callback.
		var wordSuggestion = event.target.innerHTML + '$word$suggestion$sep$' + event.target.id;
		var argument = Typps.Utility.getCommandArgument('wordsuggestion', this.get_callbacks());
		var formKeyValuePair = { formdata: argument.commandArgument };
		formKeyValuePair[this._uniqueId + '$wordforsuggestion'] = wordSuggestion;
		formKeyValuePair[this._uniqueId + '$ignorewords'] = this._ignoreWords.value;
		formKeyValuePair[this._uniqueId + '$displayspellingcompletemessage'] = (this._displaySpellingCompleteMessage == true && this._spellCheckerCompleteMessagePopup == null) ? 'true' : '';
		formKeyValuePair[this._uniqueId + '$dictionaryselection'] = this._selectedDictionary;
		this._fireUpdatePanelTrigger(formKeyValuePair, argument.commandArgument, argument.message);
	},
	_createSpellChecker: function (lang) {
		if (this._dropDownListSpellChecker === null) {
			var id = this.get_id() + '_ddlspellchecker';
			var commandName = 'spell';

			var spellToolBarItem = this._toolBars.getToolBarItem(commandName);
			var title = spellToolBarItem.get_title();
			var targetControl = spellToolBarItem.get_element();
			var listItemClassName = this._className + '-dropdownspellchecker';
			var languages = lang.split(';');
			var list = [];
			for (var index in languages) {
				var item = languages[index].split(':');
				var name = item[0];
				var value = item[1];
				Array.add(list, { text: name, value: value, toolTip: name });
			}
			var selectedStyle = this._className + '-dropdownspellcheckeractive';

			var options = this._createDropDownListOptions(listItemClassName, title, commandName, targetControl, list, null, null, true, selectedStyle);
			this._dropDownListSpellChecker = this._createDropDownList(id, options);

			if (this._ddlSpellCheckerSelectDelegate === null)
				this._ddlSpellCheckerSelectDelegate = Function.createDelegate(this, this._ddlSpellCheckerSelectHandler);
			this._dropDownListSpellChecker.add_listItemSelected(this._ddlSpellCheckerSelectDelegate);

			if (this._ddlSpellCheckerCloseDelegate === null)
				this._ddlSpellCheckerCloseDelegate = Function.createDelegate(this, this._ddlSpellCheckerCloseHandler);
			this._dropDownListSpellChecker.add_close(this._ddlSpellCheckerCloseDelegate);
		}
		this._dropDownListSpellChecker.show();
	},
	_disposeSpellCheckerElements: function () {
		if (this.iframe != null && this.iframe.body != null) {
			var spellCheckers = this.iframe.body.getElementsByTagName('b');
			var spellArray = new Array();
			for (var num1 = 0; num1 < spellCheckers.length; num1++) {
				spellArray[spellArray.length] = spellCheckers[num1];
			}
			for (var num2 = 0; num2 < spellArray.length; num2++) {
				var b = spellArray[num2];
				var isSpellChecker = Typps.Utility.containsCssClass(b, this._className + '-misspelledword');
				if (isSpellChecker) {
					var w = b.innerHTML;
					Sys.UI.DomEvent.clearHandlers(b);
					b.parentNode.replaceChild(this.iframe.createTextNode(w), b);
				}
			}
		}
	},
	_ddlSpellCheckerSelectHandler: function (sender, args) {
		this._disposeSuggestionDropDownList(null); // first clear all suggestion dropdownlists, if any.
		this._disposeSpellCheckerElements(); // then remove any previously spell checked items
		this._selectedDictionary = args.get_selectedValue();
		this._editorText.value = this.get_htmlText();
		var argument = Typps.Utility.getCommandArgument('selecteddictionary', this.get_callbacks());
		var formKeyValuePair = { formdata: argument.commandArgument };
		if (!this._postbackAllFormData)
			formKeyValuePair[this._editorText.name] = this._editorText.value;
		formKeyValuePair[this._uniqueId + '$dictionaryselection'] = this._selectedDictionary;
		formKeyValuePair[this._uniqueId + '$ignorewords'] = this._ignoreWords.value;
		formKeyValuePair[this._uniqueId + '$displayspellingcompletemessage'] = (this._displaySpellingCompleteMessage == true) ? 'true' : '';
		this._fireUpdatePanelTrigger(formKeyValuePair, argument.commandArgument, argument.message);
	},
	_ddlSpellCheckerCloseHandler: function (sender, args)
	{ },
	_addWordPastingCleanedUp: function (markup) {
		var parts = markup.split('$Html$ErrorLog$Sep$');
		var container = this.iframe.createElement('div');
		var content = Typps.Utility.getAdjacentHTML(parts[0], container);
		this.rangeComponent.insertBlockLevelElement(content, this._lastRange);
		if (parts[1] != '') {
			this._warningsLog.innerHTML = parts[1];
		}
		this._ensureLastParagraph();
	},
	_createWordPasteCleanup: function (markup) {
		if (this._wordCleanupWindow === null) {
			var container = document.createElement('div');
			var content = Typps.Utility.getAdjacentHTML(markup, container).firstChild;
			var ok = this._wordCleanupId + '_btnok';
			var cancel = this._wordCleanupId + '_btncancel';
			this._wordCleanupWindow = $create(Typps.ModalPopup,
                { id: this._wordCleanupId, display: true, content: content, title: content.title, isModal: true, className: this._className, shaderColor: this._shaderColor, shaderOpacity: this._shaderOpacity, okButtonId: ok, cancelButtonId: cancel, formElementId: this._formElementId },
                null, null, null);
			if (this._wordCleanupOkDelegate === null) {
				this._wordCleanupOkDelegate = Function.createDelegate(this, this._wordCleanupOkHandler);
			}
			if (this._wordCleanupCancelDelegate === null) {
				this._wordCleanupCancelDelegate = Function.createDelegate(this, this._wordCleanupCancelHandler);
			}
			this._wordCleanupWindow.add_okButton(this._wordCleanupOkDelegate);
			this._wordCleanupWindow.add_cancelButton(this._wordCleanupCancelDelegate);
			var wordPasteIframe = $get(this._wordCleanupId + '_text').contentWindow.document;
			wordPasteIframe.designMode = 'on'; // enable rich text editing
			wordPasteIframe.open();
			wordPasteIframe.write('<html><head><meta http-equiv="Content-type" content="text/html;charset=utf-8" /></head><body></body></html>');
			wordPasteIframe.close();
		}
	},
	_wordCleanupOkHandler: function (event) {
		var doc = $get(this._wordCleanupId + '_text').contentWindow.document;
		var wordCleanupField = doc.body.innerHTML;
		doc.body.innerHTML = '';
		var argument = Typps.Utility.getCommandArgument('wordpastingcleanup', this.get_callbacks());
		var formKeyValuePair = { formdata: argument.commandArgument };
		formKeyValuePair[this._uniqueId + '$wordcleanup'] = wordCleanupField;
		this._fireUpdatePanelTrigger(formKeyValuePair, argument.commandArgument, argument.message);
	},
	_wordCleanupCancelHandler: function (event)
	{ },
	_addCodeHighlight: function (markup) {
		var container = this.iframe.createElement('div');
		var content = Typps.Utility.getAdjacentHTML(markup, container).firstChild;
		this.rangeComponent.insertBlockLevelElement(content, this._lastRange);
		this._ensureLastParagraph();
	},
	_createCodeHighlighter: function (markup) {
		if (this._codeHilighterWindow === null) {
			var container = document.createElement('div');
			var content = Typps.Utility.getAdjacentHTML(markup, container).firstChild;

			var ok = this._codeHilighterId + '_btnok';
			var cancel = this._codeHilighterId + '_btncancel';
			this._codeHilighterWindow = $create(Typps.ModalPopup,
                { id: this._codeHilighterId, display: true, content: content, title: content.title, isModal: true, className: this._className, shaderColor: this._shaderColor, shaderOpacity: this._shaderOpacity, okButtonId: ok, cancelButtonId: cancel, formElementId: this._formElementId },
                null, null, null);
			if (this._codeHilighterOkDelegate === null) {
				this._codeHilighterOkDelegate = Function.createDelegate(this, this._codeHilighterOkHandler);
			}
			if (this._codeHilighterCancelDelegate === null) {
				this._codeHilighterCancelDelegate = Function.createDelegate(this, this._codeHilighterCancelHandler);
			}
			this._codeHilighterWindow.add_okButton(this._codeHilighterOkDelegate);
			this._codeHilighterWindow.add_cancelButton(this._codeHilighterCancelDelegate);
		}
	},
	_codeHilighterOkHandler: function (event) {
		var text = $get(this._codeHilighterId + '_text');
		var lang = $get(this._codeHilighterId + '_language');
		var showLang = new Boolean($get(this._codeHilighterId + '_showlanguage').checked);
		var enableLineNumber = new Boolean($get(this._codeHilighterId + '_linenumber').checked);
		codeHilighter = text.value
        + '$code$hilighter$sep$' + enableLineNumber.toString()
        + '$code$hilighter$sep$' + lang.options[lang.selectedIndex].value
        + '$code$hilighter$sep$' + showLang.toString();
		text.value = '';
		var argument = Typps.Utility.getCommandArgument('codehilighting', this.get_callbacks());
		var formKeyValuePair = { formdata: argument.commandArgument };
		formKeyValuePair[this._uniqueId + '$codehilighting'] = codeHilighter;
		this._fireUpdatePanelTrigger(formKeyValuePair, argument.commandArgument, argument.message);
	},
	_codeHilighterCancelHandler: function (args) { },
	_getToolBarButtonByCommand: function (container, command) {
		if (container == null)
			container = $get(this.get_id());
		var aList = container.getElementsByTagName('a');
		for (var num1 = 0; num1 < aList.length; num1++) {
			var a = aList[num1];
			var commandName = a.getAttribute('commandname');
			if (commandName == command)
				return a;
		}
		return null;
	},
	_createFileUploader: function (markup) {
		var container = document.createElement('div');
		this._fileUploaderWindow = this._createModalPopup(markup, this._fileUploaderId, true);
		if (this._btnFileUploaderOkDelegate === null) {
			this._btnFileUploaderOkDelegate = Function.createDelegate(this, this._btnFileUploaderOkHandler);
			this._fileUploaderWindow.add_okButton(this._btnFileUploaderOkDelegate);
		}
		if (this._btnFileUploaderCancelDelegate === null) {
			this._btnFileUploaderCancelDelegate = Function.createDelegate(this, this._btnFileUploaderCancelHandler);
			this._fileUploaderWindow.add_cancelButton(this._btnFileUploaderCancelDelegate);
		}
		var input = $get(this._fileUploaderId + '_input');
		if (this._fileUploadMimeFilter != '')
			input.setAttribute('accept', this._fileUploadMimeFilter);
	},
	_btnFileUploaderOkHandler: function (args) {
		this.refreshFileBrowserWindow();
		var file1 = $get(this._fileUploaderId + '_input');
		if (file1.value == '')
			return;
		var iframe = this._getIframe(this._fileUploaderId + '_iframe', this._form, false);
		if (this._iframeFileUploadDelegate === null) {
			this._iframeFileUploadDelegate = Function.createDelegate(this, this._iframeFileUploadHandler);
			Sys.UI.DomEvent.addHandler(iframe, 'load', this._iframeFileUploadDelegate);
		}
		var target = this._form.target;
		this._form.target = iframe.name;
		this._form.__EVENTTARGET.value = this._fileUploaderId;
		this._form.__EVENTARGUMENT.value = Sys.Serialization.JavaScriptSerializer.serialize({ id: file1.name, clientSidePath: file1.value });

		var eventArgs = new Typps.EventArgs();
		eventArgs.set_commandArgument(this._fileUploadingMessage);

		if (this._updatePanelProgress === null)
			this._updatePanelProgress = $find(this._updatePanelProgressId);

		this._updatePanelProgress.set_loadingMessage(this._fileUploadingMessage);
		this._updatePanelProgress.showProgressBar();

		this._beginRequestHandler(this, eventArgs);

		this._form.submit();
		this._form.target = target;
		this._form.__EVENTTARGET.value = '';
		this._form.__EVENTARGUMENT.value = '';
	},
	_iframeFileUploadHandler: function (args) {
		if (this._updatePanelProgress !== null)
			this._updatePanelProgress.hideProgressBar();
		var response = Sys.Serialization.JavaScriptSerializer.deserialize(args.target.contentWindow.document.body.firstChild.innerHTML);
		var path = response.serverSideFilePath;
		if (path != null && path != '') {
			var url = $get(this._hyperlinkId + '_url');
			url.value = path;
		}
	},
	refreshFileBrowserWindow: function (args) {
		if (this._fileBrowserWindow != null) {
			if (this._btnFileBrowserOkDelegate)
				delete this._btnFileBrowserOkDelegate;
			if (this._btnFileBrowserCancelDelegate)
				delete this._btnFileBrowserCancelDelegate;
			if (this._btnFileBrowserUploadDelegate) {
				Sys.UI.DomEvent.addHandler($get(this._fileBrowserId + '_btnupload'), 'click', this._btnFileBrowserUploadDelegate);
				delete this._btnFileBrowserUploadDelegate;
			}
			this._btnFileBrowserOkDelegate = null;
			this._btnFileBrowserCancelDelegate = null;
			this._btnFileBrowserUploadDelegate = null;
			this._disposeTreeView();

			this._fileBrowserWindow.dispose();
			delete this._fileBrowserWindow;
		}
	},
	_btnFileUploaderCancelHandler: function (args) {
	},
	_createFileBrowser: function (markup) {
		var container = document.createElement('div');
		this._fileBrowserWindow = this._createModalPopup(markup, this._fileBrowserId, true);
		var btnUpload = $get(this._fileBrowserId + '_btnupload');
		if (this._btnFileBrowserOkDelegate === null) {
			this._btnFileBrowserOkDelegate = Function.createDelegate(this, this._btnFileBrowserOkHandler);
			this._fileBrowserWindow.add_okButton(this._btnFileBrowserOkDelegate);
		}
		if (this._btnFileBrowserCancelDelegate === null) {
			this._btnFileBrowserCancelDelegate = Function.createDelegate(this, this._btnFileBrowserCancelHandler);
			this._fileBrowserWindow.add_cancelButton(this._btnFileBrowserCancelDelegate);
			this._fileBrowserWindow.add_popupCloseButton(this._btnFileBrowserCancelDelegate);
		}
		if (this._btnFileBrowserUploadDelegate === null && this._enableFileUpload) {
			this._btnFileBrowserUploadDelegate = Function.createDelegate(this, this._btnFileBrowserUploadHandler);
			Sys.UI.DomEvent.addHandler(btnUpload, 'click', this._btnFileBrowserUploadDelegate);
		}
		if (!this._enableFileUpload)
			btnUpload.style.display = 'none';

		var treeview = $get(this.get_id() + '_treeview');
		var rootElements = new Array();
		var leafElements = new Array();
		var classNames1 = { a: 'nodecollapse', b: 'nodeexpand', c: 'clickablenonlink' };
		var classNames2 = { a: 'nonlink' };
		this._getElementsByClassName(treeview, 'span', classNames1, rootElements);
		this._getElementsByClassName(treeview, 'b', classNames1, rootElements);
		this._getElementsByClassName(treeview, 'span', classNames2, leafElements);
		var num1;

		for (num1 = 0; num1 < rootElements.length; num1++) {
			var span = rootElements[num1];
			if (this._toggleTreeViewStateDelegate === null) {
				this._toggleTreeViewStateDelegate = Function.createDelegate(this, this._toggleTreeViewStateHandler);
			}
			Sys.UI.DomEvent.addHandler(span, 'click', this._toggleTreeViewStateDelegate);
		}
		if (leafElements.length > 0 && this._leafNodeClickDelegate === null)
			this._leafNodeClickDelegate = Function.createDelegate(this, this._leafNodeClickHandler);

		for (num1 = 0; num1 < leafElements.length; num1++) {
			span = leafElements[num1];
			Sys.UI.DomEvent.addHandler(span, 'click', this._leafNodeClickDelegate);
		}
	},
	_btnFileBrowserOkHandler: function (args) {
		if (this._selectedFileUrl != null) {
			var url = $get(this._hyperlinkId + '_url');
			url.value = this._selectedFileUrl;
		}
		this._selectedFileUrl = null;
		var selectedClass = 'nodeselected';
		this._removeClassFromAllLeafNodes(selectedClass);
	},
	_btnFileBrowserCancelHandler: function (args) {
		this._selectedFileUrl = null;
		var selectedClass = 'nodeselected';
		this._removeClassFromAllLeafNodes(selectedClass);
	},
	_btnFileBrowserUploadHandler: function (args) {
		var argument = Typps.Utility.getCommandArgument('fileupload', this.get_callbacks());
		var formKeyValuePair = { formdata: argument.commandArgument };
		if (this._fileUploaderWindow == null)
			this._fireUpdatePanelTrigger(formKeyValuePair, argument.commandArgument, argument.message);
		else
			this._fileUploaderWindow.show(true);
	},
	_btnBrowseServerHandler: function (args) {
		this._fileBrowserInitCallback('filebrowser');
	},
	_leafNodeClickHandler: function (args) {
		var container = args.target.parentNode;
		//get hyperlink url textbox and upate it
		var text = this._getElementByLocation(container, 'span', 0).innerHTML;
		this._selectedFileUrl = this._getElementByLocation(container, 'b', 0).innerHTML;
		var selectedClass = 'nodeselected';
		this._removeClassFromAllLeafNodes(selectedClass);
		this._toggleCssClass(container, selectedClass);
	},
	_removeClassFromAllLeafNodes: function (className) {
		var leafElements = new Array();
		var treeview = $get(this.get_id() + '_treeview');
		this._getElementsByClassName(treeview, 'span', { a: 'nonlink' }, leafElements);
		for (var num1 = 0; num1 < leafElements.length; num1++) {
			var leafNode = leafElements[num1];
			var containsClass = Typps.Utility.containsCssClass(leafNode, className);
			if (containsClass)
				this._toggleCssClass(leafNode, className);
		}
	},
	_toggleTreeViewStateHandler: function (event) {
		var parentNode = null;
		if (event.target.className == '')
			parentNode = event.target.parentNode.parentNode;
		else
			parentNode = event.target.parentNode;
		var leafNodes = parentNode.getElementsByTagName('ul');
		var stateNode = this._getElementByLocation(parentNode, 'b', 0);
		this._toggleCssClass(leafNodes[0], 'nodehide');
		if (stateNode == null)
			return;
		var containsClass = Typps.Utility.containsCssClass(stateNode, 'nodeexpand');
		if (containsClass)
			stateNode.className = 'nodecollapse';
		else
			stateNode.className = 'nodeexpand';
	},
	_getElementByLocation: function (element, tagName, index) {
		var location = 0;
		for (var num1 = 0; num1 < element.childNodes.length; num1++) {
			var elm = element.childNodes[num1];
			if (elm.nodeName.toLowerCase() == tagName.toLowerCase()) {
				if (location == index)
					return elm;
				else
					location++;
			}
		}
		return null;
	},
	_getElementsByClassName: function (element, tagName, className, collection) {
		if (element == null)
			return new Array();
		var elems = element.getElementsByTagName(tagName);
		for (var num1 = 0; num1 < elems.length; num1++) {
			var elm = elems[num1];
			var containsClass = false;
			for (var s in className) {
				containsClass = Typps.Utility.containsCssClass(elm, className[s]);
				if (containsClass) {
					collection[collection.length] = elm;
					break;
				}
			}
		}
		return collection;
	},
	_createHyperlink: function (markup) {
		if (this._hyperlinkWindow === null) {
			var container = document.createElement('div');
			var content = Typps.Utility.getAdjacentHTML(markup, container).firstChild;
			var ok = this._hyperlinkId + '_btnok';
			var cancel = this._hyperlinkId + '_btncancel';
			this._hyperlinkWindow = $create(Typps.ModalPopup,
                { id: this._hyperlinkId, display: true, content: content, title: content.title, isModal: true, className: this._className, shaderColor: this._shaderColor, shaderOpacity: this._shaderOpacity, okButtonId: ok, cancelButtonId: cancel, formElementId: this._formElementId },
                null, null, null);
			var buttonBrowseServer = $get(this._hyperlinkId + '_btnbrowse');
			if (!this._enableFileBrowser)
				buttonBrowseServer.style.visibility = 'hidden';
			if (this._hyperlinkTypeChangeDelegate === null) {
				this._hyperlinkTypeChangeDelegate = Function.createDelegate(this, this._hyperlinkTypeChangeHandler);
				Sys.UI.DomEvent.addHandler($get(this._hyperlinkId + '_type'), 'change', this._hyperlinkTypeChangeDelegate);
			}
			if (this._btnHyperlinkloaderOkDelegate === null) {
				this._btnHyperlinkloaderOkDelegate = Function.createDelegate(this, this._btnHyperlinkloaderOkHandler);
				this._hyperlinkWindow.add_okButton(this._btnHyperlinkloaderOkDelegate);
			}
			if (this._btnHyperlinkloaderCancelDelegate === null) {
				this._btnHyperlinkloaderCancelDelegate = Function.createDelegate(this, this._btnHyperlinkloaderCancelHandler);
				this._hyperlinkWindow.add_cancelButton(this._btnHyperlinkloaderCancelDelegate);
				this._hyperlinkWindow.add_popupCloseButton(this._btnHyperlinkloaderCancelDelegate);
			}
			if (this._btnBrowseServerDelegate === null && this._enableFileBrowser) {
				this._btnBrowseServerDelegate = Function.createDelegate(this, this._btnBrowseServerHandler);
				Sys.UI.DomEvent.addHandler(buttonBrowseServer, 'click', this._btnBrowseServerDelegate);
			}
			this._editHyperlink();
		}
	},
	_editHyperlink: function () {
		var selectedItem = this.rangeComponent.getAllNodesInRange(this._lastRange),
		nodes = selectedItem.get_nodes(),
		length = nodes.length,
		hasSelection = selectedItem.get_hasSelection(),
		activeNode = null,
		i,
		length = nodes.length,
		node;
		if (hasSelection && nodes.length > 0) {
			for (i = 0; i < length; i++) {
				node = nodes[i];
				if (node.nodeType == 3/*TEXT_NODE*/) {
					//Non-IE browsers select only the innerHTML of
					//the currently selected element. Compensate.
					if (node.parentNode.nodeName.toLowerCase() == 'a') {
						node = node.parentNode;
					}
				}
				if (node.nodeType == 1/*ELEMENT_NODE*/ && node.nodeName.toLowerCase() == 'a') {
					activeNode = node;
					break;
				}
			}
		}
		else {
			activeNode = this._toggleManager.get_activeNode('a');
		}
		if (activeNode != null) {
			this._hyperlink = activeNode;
			if (this._isIE) {
				var href2 = this._hyperlink.getAttribute('href2');
				if (href2 != null)
					this._hyperlink.href = href2;
			}
			var url = $get(this._hyperlinkId + '_url');
			var inputTarget = $get(this._hyperlinkId + '_target');
			var selectType = $get(this._hyperlinkId + '_type');
			var href = decodeURI(this._hyperlink.getAttribute('href', 2));
			if (this._isIE && href2 != null)
				href = decodeURI(href2);
			if (href != '' && href.indexOf('//') != -1) {
				var protocol = href.split('//')[0];
				for (var num1 = 0; num1 < selectType.options.length; num1++) {
					var option = selectType.options[num1];
					if (option.value == protocol)
						selectType.selectedIndex = num1;
				}
			}
			var match = "javascript:void window.open('";
			var startIndex = href.indexOf(match);
			if (startIndex != -1) {
				inputTarget.checked = true;
				var endIndex = href.indexOf("')");
				if (endIndex != -1)
					href = href.substring(startIndex + match.length, endIndex - startIndex);
			}
			url.value = href;
		}
	},
	_hyperlinkTypeChangeHandler: function (event) {
		var url = $get(this._hyperlinkId + '_url');
		var inputTarget = $get(this._hyperlinkId + '_target');
		var text = this._getUrlText(url.value);
		var doubleForwardSlash = '//';
		var value = event.target.options[event.target.selectedIndex].value;
		if (value == 'javascript:') {
			doubleForwardSlash = '';
			inputTarget.disabled = true;
		}
		else {
			inputTarget.disabled = false;
		}
		url.value = value + doubleForwardSlash + text;
	},
	_btnHyperlinkloaderOkHandler: function (event) {
		var selectType = $get(this._hyperlinkId + '_type');
		var inputTarget = $get(this._hyperlinkId + '_target');
		var formatString = "javascript:void window.open('{0}')";
		var url = $get(this._hyperlinkId + '_url');
		var urlValue = url.value;
		var range = this._lastRange;
		if (range.select) {
			range.select();
		}
		else {
			this._maintainSelection();
		}
		var hyperlink = this._hyperlink;


		var marker = '$temp$typps$anchor$href';
		if (hyperlink == null) {
			this.iframe.execCommand('CreateLink', false, marker);
			hyperlink = this._getElementByMarker(marker, 'a');
			if (hyperlink == null) {
				//no selection was made
				hyperlink = this.iframe.createElement('a');
				this.rangeComponent.insertNodeAtSelection(hyperlink, range);
			}
		}
		if (hyperlink != null) {
			if (!inputTarget.disabled && inputTarget.checked == true)
				urlValue = String.format(formatString, urlValue);

			if (this._isIE && !this._autoResolveToAbsolutePath)
				hyperlink.setAttribute('href2', urlValue);
			hyperlink.href = urlValue;
			var anchorText = hyperlink.innerHTML.toLowerCase();
			if (Typps.Utility.isNullOrEmpty(anchorText) || anchorText.indexOf(marker) != -1) {
				//webkit is tolerant to no selection being made
				//but the link contains our marker
				//so default to url
				hyperlink.innerHTML = urlValue;
			}
		}
		selectType.selectedIndex = 3; //http:
		url.value = 'http://';
		inputTarget.checked = false;
		inputTarget.disabled = false;
		this._hyperlink = null; //reset
	},
	_getElementByMarker: function (marker, elmName) {
		var body = this.iframe.body;
		var elements = this.iframe.body.getElementsByTagName(elmName);
		for (var num1 = 0; num1 < elements.length; num1++) {
			var elm = elements[num1];
			if (elm.href.toLowerCase().indexOf(marker) != -1)
				return elm;
		}
		return null;
	},
	_getUrlText: function (text) {
		var text1 = null;
		if (text.indexOf('//') != -1)
			text1 = text.split('//');
		else if (text.indexOf('://') != -1)
			text1 = text.split('://');
		else if (text.indexOf(':/') != -1)
			text1 = text.split(':/');
		else if (text.indexOf(':') != -1)
			text1 = text.split(':');
		else
			return text;
		return text1[1];
	},
	_btnHyperlinkloaderCancelHandler: function (event) {
		var selectType = $get(this._hyperlinkId + '_type');
		var url = $get(this._hyperlinkId + '_url');
		var inputTarget = $get(this._hyperlinkId + '_target');
		selectType.selectedIndex = 3; //http:
		url.value = 'http://';
		inputTarget.checked = false;
		inputTarget.disabled = false;
		this._hyperlink = null; //reset
	},
	_createColorPicker: function (args) {
		this._colorPicker = $find(this._colorPickerId);
		var command = args.get_commandName();
		var target = args.get_innerArgs().target;
		var title = target.title;
		if (this._colorPicker !== null) {
			if (this._btnColorPickerOkDelegate === null) {
				this._btnColorPickerOkDelegate = Function.createDelegate(this, this._btnColorPickerOkHandler);
				this._btnColorPickerCancelDelegate = Function.createDelegate(this, this._btnColorPickerCancelHandler);
				this._colorPicker.add_okButton(this._btnColorPickerOkDelegate);
				this._colorPicker.add_cancelButton(this._btnColorPickerCancelHandler);
			}
			this._colorPicker.set_commandName(command);
			this._colorPicker.set_commandArgument(args.get_commandArgument());
			this._colorPicker.resetTitle(title);
			this._colorPicker.initializeRequest();
		}
	},
	_btnColorPickerOkHandler: function (sender, args) {
		var h = this.get_events().getHandler('colorSelect');
		if (h) h(this, args);
		var command = args.get_commandName();
		var color = args.get_commandArgument();
		switch (command) {
			case 'cellbordercolor':
			case 'cellbackgroundcolor':
			case 'tablebordercolor':
			case 'tablebackgroundcolor':
				var elem = sender.get_commandArgument();
				elem.style.backgroundColor = color;
				return;
		}
		this._maintainSelection();
		if (this._isIE) {
			switch (command) {
				case 'forecolor':
				case 'backcolor':
					var text = this._lastRange.text;
					if (text != '') {
						this._lastRange.collapse();
						this._lastRange.findText(text);
					}
					var parentNode = this._lastRange.parentElement();
					if (parentNode.nodeName.toLowerCase() == 'span') {
						var flag1 = false;
						if ('forecolor' && parentNode.style.color != '') {
							flag1 = true;
							parentNode.style.color = color;
						} else if ('backcolor' && parentNode.style.backgroundColor != '') {
							flag1 = true;
							parentNode.style.backgroundColor = color;
						}
						if (flag1) {
							this._maintainSelection(parentNode);
							return;
						}
					}
					this.iframe.execCommand(command, false, color);
					this._fixDeprecatedFontElements(command);
					break;
			}
		}
		else {
			this.iframe.execCommand(command, false, color);
		}
	},
	_fixDeprecatedFontElements: function (command) {
		var fonts = this.iframe.getElementsByTagName('font');
		var length = fonts.length - 1;
		//when deleting do it in reverse order or
		//the position of the list changes.
		for (var num1 = length; num1 >= 0; num1--) {
			var font = fonts[num1];
			var span = this.iframe.createElement('span');
			if (font.innerHTML != null && font.innerHTML != undefined)
				span.innerHTML = font.innerHTML;
			var color = null;
			switch (command) {
				case 'forecolor':
					color = font.getAttribute('color');
					if (color == null)
						color = font.style.color;
					span.style.color = color;
					break;
				case 'backcolor':
					color = font.getAttribute('backcolor');
					if (color == null)
						color = font.style.backgroundColor;
					span.style.backgroundColor = color;
					break;
				case 'fontsize':
					if (this._isFF && font.childNodes.length == 1) {
						var cNode = font.childNodes[0];
						if (cNode != null && cNode.nodeType == 1) {
							var nodeName = cNode.nodeName.toLowerCase();
							if (nodeName == 'span' && cNode.style.fontSize != '')
								span = cNode;
						}
					}
					var fontSize = font.getAttribute('size');
					if (fontSize != null)
						span.style.fontSize = this._getCssSize(fontSize);
					break;
			}
			font.parentNode.replaceChild(span, font);
			if (num1 == 0)
				this._maintainSelection(span);
		}
	},
	_getCssSize: function (size) {
		var validSize = size;
		switch (size) {
			case '1':
				validSize = 'xx-small';
				break;
			case '2':
				validSize = 'x-small';
				break;
			case '3':
				validSize = 'small';
				break;
			case '4':
				validSize = 'medium';
				break;
			case '5':
				validSize = 'large';
				break;
			case '6':
				validSize = 'x-large';
				break;
			case '7':
				validSize = 'xx-large';
				break;
		}
		return validSize;
	},
	_maintainSelection: function (elem, collapse) {
		if (collapse == null)
			collapse = true; //put selection in the beginning of textrange(default)
		if (this._lastRange == null)
			this._lastRange = this.rangeComponent.createRange();
		var range = this._lastRange;
		try {
			if (this._isIE && Sys.Browser.version < 9) {
				var flag1 = false;
				var text = range.text;
				range.collapse();
				if (elem != null) {
					try {
						range.moveToElementText(elem);
						if (!collapse)
							range.collapse(collapse); //put the cursor after this element
					} catch (exception) {
						if (exception.number == -2147024809)/*Invalid argument, most likely element is not part of the document yada dada whatever, shouldn't happen*/
							flag1 = true;
					}
				}
				if (flag1 || elem == null) {
					range.moveToBookmark(this.rangeComponent._bookmark);
					if (text != '')
						range.findText(text);
				}
				if (range.select) {
					range.select();
				}
			} else {
				if (elem != null) {
					if (elem.hasChildNodes())
						elem = elem.lastChild;

					range.selectNode(elem);
					if (!collapse)
						range.collapse(collapse);
				}
				else {
					range.setStart(range.startContainer, range.startOffset);
					range.setEnd(range.endContainer, range.endOffset);
				}
				var selection = this.contentWindow.getSelection();
				selection.addRange(range);
				this.iframeElement.focus();
			}
		} catch (exception) { }
	},
	_btnColorPickerCancelHandler: function (sender, args) {
	},
	_createImageDesigner: function () {
		this._imageDesigner = $find(this._imagePickerId);
		if (this._imageDesigner !== null) {
			if (this._btnImageDesignerOkDelegate === null) {
				this._btnImageDesignerOkDelegate = Function.createDelegate(this, this._btnImageDesignerOkHandler);
				this._btnImageDesignerCancelDelegate = Function.createDelegate(this, this._btnImageDesignerCancelHandler);
				this._imageDesigner.add_okButton(this._btnImageDesignerOkDelegate);
				this._imageDesigner.add_cancelButton(this._btnImageDesignerCancelHandler);
				this._imageDesigner.set_document(this.iframe);
			}
		}
		var activeNode = this._toggleManager.get_activeNode('img');
		this._imageDesigner._initializeRequest(activeNode);
	},
	refreshImageBrowser: function () {
		if (this._imageDesigner !== null)
			this._imageDesigner.refreshImageBrowserWindow();
	},
	_btnImageDesignerCancelHandler: function (sender, args) {
	},
	_btnImageDesignerOkHandler: function (sender, args) {
		var image = args.get_image();
		var range = null;
		if (this._isIE && image != null) {
			image.removeAttribute('height');
			image.removeAttribute('width');
			if (!this._autoResolveToAbsolutePath)
				image.setAttribute('src2', args.get_commandArgument());
		}
		if (args.get_isNew() && image != null) {
			var img = this.iframe.createElement('img');

			this.rangeComponent.insertNodeAtSelection(image, this._lastRange);
		}
		this._ensureLastParagraph();
	},
	_ensureImgWidthAndHeight: function () {
		var images = this.iframe.body.getElementsByTagName('IMG');
		for (var num1 = 0; num1 < images.length; num1++) {
			var img = images[num1];
			var width = img.getAttribute('width');
			var height = img.getAttribute('height');
			if (width != null) {
				width = parseInt(width);
				if (!isNaN(width))
					img.style.width = width + 'px';
				img.removeAttribute('width');
			}
			if (height != null) {
				height = parseInt(height);
				if (!isNaN(height))
					img.style.height = height + 'px';
				img.removeAttribute('height');
			}
		}
	},
	_createCellsDesigner: function (markup) {
		if (this._cellDesignerWindow == null) {
			this._cellDesignerWindow = this._createModalPopup(markup, this._cellDesignerId, false);
			if (this._ckCellWidthDelegate === null) {
				this._ckCellWidthDelegate = Function.createDelegate(this, this._ckCellWidthHandler);
			}
			if (this._ckCellHeightDelegate === null) {
				this._ckCellHeightDelegate = Function.createDelegate(this, this._ckCellHeightHandler);
			}
			if (this._btnCellBorderColorDelegate === null) {
				this._btnCellBorderColorDelegate = Function.createDelegate(this, this._btnCellBorderColorHandler);
			}
			if (this._btnCellBackGroundColorDelegate === null) {
				this._btnCellBackGroundColorDelegate = Function.createDelegate(this, this._btnCellBackGroundColorHandler);
			}
			if (this._btnCellOkDelegate === null) {
				this._btnCellOkDelegate = Function.createDelegate(this, this._btnCellOkHandler);
			}
			if (this._btnCellCancelDelegate === null) {
				this._btnCellCancelDelegate = Function.createDelegate(this, this._btnCellCancelHandler);
			}

			if (this._ckTableCellBorderDelegate === null) {
				this._ckTableCellBorderDelegate = Function.createDelegate(this, this._ckTableCellBorderHandler);
			}
			Sys.UI.DomEvent.addHandler($get(this._cellDesignerId + '_ckwidth'), 'click', this._ckCellWidthDelegate);
			Sys.UI.DomEvent.addHandler($get(this._cellDesignerId + '_ckheight'), 'click', this._ckCellHeightDelegate);
			Sys.UI.DomEvent.addHandler($get(this._cellDesignerId + '_btnbordercolor'), 'click', this._btnCellBorderColorDelegate);
			Sys.UI.DomEvent.addHandler($get(this._cellDesignerId + '_btnbackgroundcolor'), 'click', this._btnCellBackGroundColorDelegate);
			Sys.UI.DomEvent.addHandler($get(this._cellDesignerId + '_ckborder'), 'click', this._ckTableCellBorderDelegate);
			this._cellDesignerWindow.add_okButton(this._btnCellOkDelegate);
			this._cellDesignerWindow.add_cancelButton(this._btnCellCancelDelegate);
		}
		this._getCellProperties(Typps.Editor.CommandType.Edit);
	},
	_ckCellWidthHandler: function (event) {
		this._toggleDisability(this._cellDesignerId, event.target, $get(this._cellDesignerId + '_selunits1'), $get(this._cellDesignerId + '_txtwidth'));
	},
	_ckCellHeightHandler: function (event) {
		this._toggleDisability(this._cellDesignerId, event.target, $get(this._cellDesignerId + '_selunits2'), $get(this._cellDesignerId + '_txtheight'));
	},
	_ckTableCellBorderHandler: function (event) {
		var borderWidth = $get(this._cellDesignerId + '_txtborder');
		var borderStyle = $get(this._cellDesignerId + '_selcellborder');
		var btnBorderColor = $get(this._cellDesignerId + '_btnbordercolor');
		var borderColor = $get(this._cellDesignerId + '_bordercolorpreview');
		var status = (event.target.checked) ? false : true;
		borderWidth.disabled = status;
		borderStyle.disabled = status;
		var visibility = status ? 'hidden' : 'visible';
		borderColor.style.visibility = visibility;
		btnBorderColor.style.visibility = visibility;
		borderWidth.value = status ? 0 : 1;
		if (status) {
			borderColor.style.backgroundColor = '';
			borderStyle.selectedIndex = 0;
		}
	},
	_btnCellBorderColorHandler: function (args) {
		var colorNode = $get(this._cellDesignerId + '_bordercolorpreview');
		var eventArgs = new Typps.EventArgs();
		eventArgs.set_commandName('cellbordercolor');
		eventArgs.set_commandArgument(colorNode);
		eventArgs.set_innerArgs(args);
		this._createColorPicker(eventArgs);
	},
	_btnCellBackGroundColorHandler: function (args) {
		var colorNode = $get(this._cellDesignerId + '_bgcolorpreview');
		var eventArgs = new Typps.EventArgs();
		eventArgs.set_commandName('cellbackgroundcolor');
		eventArgs.set_commandArgument(colorNode);
		eventArgs.set_innerArgs(args);
		this._createColorPicker(eventArgs);
	},
	_btnCellOkHandler: function (args) {
		this._setCellProperties();
	},
	_btnCellCancelHandler: function (args) {
		this._getCellProperties(Typps.Editor.CommandType.Cancel); //simply reset defaults.
	},
	_createModalPopup: function (markup, id, makeFormChild) {
		var container = document.createElement('div');
		var content = Typps.Utility.getAdjacentHTML(markup, container).firstChild;
		var ok = id + '_btnok';
		var cancel = id + '_btncancel';
		var popup = $create(Typps.ModalPopup,
            { id: id, display: true, content: content, title: content.title, isModal: true, className: this._className, shaderColor: this._shaderColor, shaderOpacity: this._shaderOpacity, okButtonId: ok, cancelButtonId: cancel, makeFormChild: makeFormChild, formElementId: this._formElementId },
            null, null, null);
		content.removeAttribute('title');

		return popup;

	},
	_createTableDesigner: function (markup) {
		if (this._tableDesignerWindow == null) {
			var id = this._tableDesignerId;
			this._tableDesignerWindow = this._createModalPopup(markup, id, false);

			if (this._ckTableWidthDelegate === null) {
				this._ckTableWidthDelegate = Function.createDelegate(this, this._ckTableWidthHandler);
			}
			if (this._ckTableHeightDelegate === null) {
				this._ckTableHeightDelegate = Function.createDelegate(this, this._ckTableHeightHandler);
			}
			if (this._ckTableBorderDelegate === null) {
				this._ckTableBorderDelegate = Function.createDelegate(this, this._ckTableBorderHandler);
			}
			if (this._ckTablePaddingDelegate === null) {
				this._ckTablePaddingDelegate = Function.createDelegate(this, this._ckTablePaddingHandler);
			}
			if (this._ckTableSpacingDelegate === null) {
				this._ckTableSpacingDelegate = Function.createDelegate(this, this._ckTableSpacingHandler);
			}
			if (this._btnTableBorderColorDelegate === null) {
				this._btnTableBorderColorDelegate = Function.createDelegate(this, this._btnTableBorderColorHandler);
			}
			if (this._btnTableBackgroundColorDelegate === null) {
				this._btnTableBackgroundColorDelegate = Function.createDelegate(this, this._btnTableBackgroundColorHandler);
			}
			if (this._btnTableOkDelegate === null) {
				this._btnTableOkDelegate = Function.createDelegate(this, this._btnTableOkHandler);
			}
			if (this._btnTableAddNewDelegate === null) {
				this._btnTableAddNewDelegate = Function.createDelegate(this, this._btnTableAddNewHandler);
			}
			if (this._btnTableCancelDelegate === null) {
				this._btnTableCancelDelegate = Function.createDelegate(this, this._btnTableCancelHandler);
			}

			Sys.UI.DomEvent.addHandler($get(id + '_ckwidth'), 'click', this._ckTableWidthDelegate);
			Sys.UI.DomEvent.addHandler($get(id + '_ckheight'), 'click', this._ckTableHeightDelegate);
			Sys.UI.DomEvent.addHandler($get(id + '_ckborder'), 'click', this._ckTableBorderDelegate);
			Sys.UI.DomEvent.addHandler($get(id + '_ckpadding'), 'click', this._ckTablePaddingDelegate);
			Sys.UI.DomEvent.addHandler($get(id + '_ckspacing'), 'click', this._ckTableSpacingDelegate);
			Sys.UI.DomEvent.addHandler($get(id + '_btnbordercolor'), 'click', this._btnTableBorderColorDelegate);
			Sys.UI.DomEvent.addHandler($get(id + '_btnbackgroundcolor'), 'click', this._btnTableBackgroundColorDelegate);
			Sys.UI.DomEvent.addHandler($get(id + '_btnaddnew'), 'click', this._btnTableAddNewDelegate);
			this._tableDesignerWindow.add_okButton(this._btnTableOkDelegate);
			this._tableDesignerWindow.add_cancelButton(this._btnTableCancelDelegate);
		}
		var commandType = (this._editableTableCell == null) ?
            Typps.Editor.CommandType.AddNew : Typps.Editor.CommandType.Edit;
		this._getTableProperties(commandType);
	},
	_setTableSizeElements: function (elm, ckWidth, ckHeight, txtWidth, txtHeight, units1, units2) {
		var styleWidth = elm.style.width;
		var styleHeight = elm.style.height;
		var widthSupplied = !isNaN(parseInt(styleWidth));
		var heightSupplied = !isNaN(parseInt(styleHeight));
		var unit = 'px';
		var len = 0;
		ckWidth.checked = widthSupplied;
		units1.disabled = !widthSupplied;
		txtWidth.disabled = !widthSupplied;
		ckHeight.checked = heightSupplied;
		units2.disabled = !heightSupplied;
		txtHeight.disabled = !heightSupplied;

		if (widthSupplied) {
			len = styleWidth.indexOf('%') != -1 ? 1 : 2;
			unit = styleWidth.substring(styleWidth.length - len);
			var u1SelectedIndex = Typps.Utility.getIndexByNameFromOptions(unit, units1.options);
			if (u1SelectedIndex != -1)
				units1.options[u1SelectedIndex].selected = true;
		}
		if (heightSupplied) {
			len = styleHeight.indexOf('%') != -1 ? 1 : 2;
			unit = styleHeight.substring(styleHeight.length - len);
			var u2SelectedIndex = Typps.Utility.getIndexByNameFromOptions(unit, units2.options);
			if (u2SelectedIndex != -1)
				units2.options[u2SelectedIndex].selected = true;
		}
		txtWidth.value = isNaN(parseInt(styleWidth)) ? 0 : parseInt(styleWidth);
		txtHeight.value = isNaN(parseInt(styleHeight)) ? 0 : parseInt(styleHeight);
	},
	_setTableBorders: function (elm, borderStyleSel, ckBorder, btnBorder, borderColor, txtBorderWidth) {
		if (elm.style.borderStyle != '') {
			borderStyleSel.disabled = false;
			var styleName = this._getFirstBorderStyle(elm);
			var borderStyleSelectedIndex = Typps.Utility.getIndexByNameFromOptions(styleName, borderStyleSel.options);
			if (borderStyleSelectedIndex != -1)
				borderStyleSel.options[borderStyleSelectedIndex].selected = true;
		}
		else {
			borderStyleSel.options[0].selected = true;
			borderStyleSel.disabled = false;
		}

		if (elm.border != '' || elm.style.borderWidth != '') {
			txtBorderWidth.disabled = false;
			ckBorder.checked = true;
			btnBorder.style.visibility = 'visible';
			borderColor.style.visibility = 'visible';
			if (elm.style.borderWidth != '')
				txtBorderWidth.value = (isNaN(parseInt(elm.style.borderWidth))) ? 0 : parseInt(elm.style.borderWidth);
			else
				txtBorderWidth.value = (isNaN(parseInt(elm.border))) ? 0 : parseInt(elm.border);
		}
		else {
			txtBorderWidth.value = 0;
			ckBorder.checked = false;
			txtBorderWidth.disabled = true;
			btnBorder.style.visibility = 'hidden';
			borderColor.style.visibility = 'hidden';
		}
	},
	_getTableProperties: function (commandType) {
		if ($get(this._tableDesignerId) == null) return;
		var tableProp = null;
		var id = this._tableDesignerId;
		var ckBorder = $get(id + '_ckborder');
		var ckPadding = $get(id + '_ckpadding');
		var ckSpacing = $get(id + '_ckspacing');
		var ckWidth = $get(id + '_ckwidth');
		var ckHeight = $get(id + '_ckheight');
		var rows = $get(id + '_rows');
		var cols = $get(id + '_cols');
		var units1 = $get(id + '_selunits1');
		var width = $get(id + '_txtwidth');
		var units2 = $get(id + '_selunits2');
		var height = $get(id + '_txtheight');
		var borderStyle = $get(id + '_seltableborder');
		var borderWidth = $get(id + '_txtborder');
		var padding = $get(id + '_txtpadding');
		var spacing = $get(id + '_txtspacing');
		var btnBorder = $get(id + '_btnbordercolor');
		var borderColor = $get(id + '_bordercolorpreview');
		var backgroundColor = $get(id + '_backgroundcolorpreview');
		var btnUpdate = $get(id + '_btnok');
		var sum = $get(id + '_txtsummary');
		btnUpdate.style.display = (this._editableTableCell == null) ? 'none' : '';

		if (commandType == Typps.Editor.CommandType.Edit && this._editableTableCell != null) {
			var editableTable = this._getAncestorByTagName(this._editableTableCell, 'table');
			if (editableTable == null) return;
			ckPadding.checked = false;
			ckSpacing.checked = false;
			if (editableTable.cellSpacing != '') {
				spacing.disabled = false;
				spacing.value = editableTable.cellSpacing;
				ckSpacing.checked = true;
			}
			if (editableTable.cellPadding != '') {
				padding.disabled = false;
				padding.value = editableTable.cellPadding;
				ckPadding.checked = true;
			}
			rows.value = editableTable.rows.length;
			this._setTableSizeElements(editableTable, ckWidth, ckHeight, width, height, units1, units2);
			this._setTableBorders(editableTable, borderStyle, ckBorder, borderColor, borderColor, borderWidth);

			borderColor.style.backgroundColor = this._getFirstBorderColor(editableTable);
			backgroundColor.style.backgroundColor = editableTable.style.backgroundColor;
			if (editableTable.summary != undefined)
				sum.value = editableTable.summary;
		}

		tableProp = {
			rows: isNaN(parseInt(rows.value)) ? 1 : parseInt(rows.value),
			cols: isNaN(parseInt(cols.value)) ? 1 : parseInt(cols.value),
			width: isNaN(parseInt(width.value)) ? 0 : parseInt(width.value),
			widthUnit: units1.options[units1.selectedIndex].value,
			height: isNaN(parseInt(height.value)) ? 0 : parseInt(height.value),
			heightUnit: units2.options[units2.selectedIndex].value,
			borderWidth: (isNaN(parseInt(borderWidth.value))) ? 0 : parseInt(borderWidth.value),
			padding: (isNaN(parseInt(padding.value))) ? 0 : parseInt(padding.value),
			spacing: (isNaN(parseInt(spacing.value))) ? 0 : parseInt(spacing.value),
			borderStyle: borderStyle.options[borderStyle.selectedIndex].value,
			borderColor: borderColor.style.backgroundColor,
			backgroundColor: backgroundColor.style.backgroundColor,
			sum: sum.value
		}
		if (commandType != Typps.Editor.CommandType.Edit) {
			// reset table designer
			rows.value = 3;
			cols.disabled = false;
			cols.value = 3;
			units1.options[1].selected = true; units1.disabled = false;
			units2.options[1].selected = true; units2.disabled = true;
			width.value = 99; width.disabled = false;
			height.value = 0; height.disabled = true;
			borderStyle.options[0].selected = true; borderStyle.disabled = false;
			borderWidth.value = 1; borderWidth.disabled = false;
			padding.value = 1; padding.disabled = false;
			spacing.value = 2; spacing.disabled = false;
			borderColor.style.backgroundColor = '';
			backgroundColor.style.backgroundColor = '';
			sum.value = '';
			ckHeight.checked = false;
			btnBorder.style.visibility = 'visible';
			ckBorder.checked = true;
			ckPadding.checked = true;
			ckSpacing.checked = true;
		}
		return tableProp;
	},
	_buildTable: function (tableProp, commandType) {
		var table = null;
		var ckBorder = $get(this._tableDesignerId + '_ckborder');
		var sb = [];

		if (commandType == Typps.Editor.CommandType.AddNew) {
			table = this.iframe.createElement('table');

			for (var num1 = 0; num1 < tableProp.rows; num1++) {
				var newRow = table.insertRow(0);
				for (var num2 = 0; num2 < tableProp.cols; num2++) {
					var newCell = newRow.insertCell(0);
					if (this._isOpera)
						newCell.appendChild(this.iframe.createTextNode('\u00A0'));
					newCell.appendChild(this.iframe.createElement('br'));
				}
			}
		}
		else {
			if (this._editableTableCell == null) return;
			table = this._getAncestorByTagName(this._editableTableCell, 'table');
		}
		table.setAttribute('cellspacing', tableProp.spacing);
		table.setAttribute('cellpadding', tableProp.padding);
		if (tableProp.width > 0)
			Array.add(sb, 'width:' + tableProp.width + tableProp.widthUnit);
		if (tableProp.height > 0)
			Array.add(sb, 'height:' + tableProp.height + tableProp.heightUnit);

		if (tableProp.borderWidth > 0) {
			table.setAttribute('border', tableProp.borderWidth);
			if (table.style.borderStyle != '' || tableProp.borderStyle.toLowerCase() != 'none')
				Array.add(sb, 'border-style:' + tableProp.borderStyle);
			if (tableProp.borderColor != '')
				Array.add(sb, 'border-color:' + tableProp.borderColor);
		}
		else {
			if (table.border != '')
				table.removeAttribute('border');
			if (table.style.borderStyle != '')
				table.style.borderStyle = '';
			if (table.style.borderColor != '')
				table.style.borderColor = '';
		}
		if (tableProp.backgroundColor != '')
			Array.add(sb, 'background-color:' + tableProp.backgroundColor);

		if (tableProp.sum != '')
			table.setAttribute('summary', summary = tableProp.sum);
		else if (table.summary != undefined)
			table.removeAttribute('summary');

		if (sb.length > 0) {
			var cssText = sb.join(';');
			if (this._isIE && Sys.Browser.version < 8)
				table.style.cssText = cssText;
			table.setAttribute('style', cssText);
		}
		else {
			table.removeAttribute('style');
		}
		if (commandType == Typps.Editor.CommandType.AddNew)
			this.rangeComponent.insertBlockLevelElement(table, this._lastRange);
		this._ensureLastParagraph();
	},
	_btnTableOkHandler: function (sender, args) {
		var tableProp = this._getTableProperties(Typps.Editor.CommandType.Update);
		if (tableProp != null)
			this._buildTable(tableProp, Typps.Editor.CommandType.Update);
	},
	_btnTableAddNewHandler: function (args) {
		var tableProp = this._getTableProperties(Typps.Editor.CommandType.AddNew);
		if (tableProp != null)
			this._buildTable(tableProp, Typps.Editor.CommandType.AddNew);
		this._tableDesignerWindow.show(false);
	},
	_btnTableCancelHandler: function (sender, args) {
		this._getTableProperties(Typps.Editor.CommandType.Cancel);
		// nothing to do here.
	},
	_getFirstBorderColor: function (elm) {
		if (elm.style.borderTopColor != '')
			return elm.style.borderTopColor;
		else if (elm.style.borderRightColor != '')
			return elm.style.borderRightColor;
		else if (elm.style.borderBottomColor != '')
			return elm.style.borderBottomColor;
		else
			return elm.style.borderLeftColor;
	},
	_getFirstBorderStyle: function (elm) {
		if (elm.style.borderTopStyle != '')
			return elm.style.borderTopStyle;
		else if (elm.style.borderRightStyle != '')
			return elm.style.borderRightStyle;
		else if (elm.style.borderBottomStyle != '')
			return elm.style.borderBottomStyle;
		else
			return elm.style.borderLeftStyle;
	},
	_getCellProperties: function (commandType) {
		if (this._editableTableCell == null) return;
		var id = this._cellDesignerId;

		if ($get(id) == null) return;
		//cell designer
		var cellProperties = null;

		var rowsspan = $get(id + '_rowsspan');
		var colsspan = $get(id + '_colsspan');
		var align = $get(id + '_horizontalalign');
		var valign = $get(id + '_verticalalign');
		var ckWidth = $get(id + '_ckwidth');
		var ckHeight = $get(id + '_ckheight');
		var width = $get(id + '_txtwidth');
		var height = $get(id + '_txtheight');
		var units1 = $get(id + '_selunits1');
		var units2 = $get(id + '_selunits2');
		var nowrap = $get(id + '_cknowrap');
		var bgColor = $get(id + '_bgcolorpreview');
		var borderColor = $get(id + '_bordercolorpreview');
		var borderStyle = $get(id + '_selcellborder');
		var borderWidth = $get(id + '_txtborder');
		var ckBorder = $get(id + '_ckborder');
		var btnBorder = $get(id + '_btnbordercolor');

		if (commandType == Typps.Editor.CommandType.Edit) {
			rowsspan.value = this._editableTableCell.rowSpan;
			colsspan.value = this._editableTableCell.colSpan;
			var alignSelectedIndex = Typps.Utility.getIndexByNameFromOptions(this._editableTableCell.align, align.options);
			var valignSelectedIndex = Typps.Utility.getIndexByNameFromOptions(this._editableTableCell.vAlign, valign.options);
			if (alignSelectedIndex != -1)
				align.options[alignSelectedIndex].selected = true;
			if (valignSelectedIndex != -1)
				valign.options[valignSelectedIndex].selected = true;

			this._setTableSizeElements(this._editableTableCell, ckWidth, ckHeight, width, height, units1, units2);
			nowrap.checked = this._editableTableCell.style.whiteSpace == 'normal';
			bgColor.style.backgroundColor = this._editableTableCell.style.backgroundColor;

			this._setTableBorders(this._editableTableCell, borderStyle, ckBorder, btnBorder, borderColor, borderWidth);
			borderColor.style.backgroundColor = this._getFirstBorderColor(this._editableTableCell);
		}
		if (commandType == Typps.Editor.CommandType.Update)//reset
		{
			cellProperties = {
				rowsspan: (isNaN(parseInt(rowsspan.value))) ? 1 : parseInt(rowsspan.value),
				colsspan: (isNaN(parseInt(colsspan.value))) ? 1 : parseInt(colsspan.value),
				align: align.options[align.selectedIndex].value,
				valign: valign.options[valign.selectedIndex].value,
				width: (isNaN(parseInt(width.value)) || width.disabled) ? '' : parseInt(width.value),
				height: (isNaN(parseInt(height.value)) || height.disabled) ? '' : parseInt(height.value),
				widthUnit: units1.options[units1.selectedIndex].value,
				heightUnit: units2.options[units2.selectedIndex].value,
				nowrap: nowrap.checked,
				bgColor: bgColor.style.backgroundColor,
				borderWidth: (isNaN(parseInt(borderWidth.value))) ? 0 : parseInt(borderWidth.value),
				borderStyle: borderStyle.options[borderStyle.selectedIndex].value,
				borderColor: borderColor.style.backgroundColor
			}
		}
		if (commandType != Typps.Editor.CommandType.Edit)//reset
		{
			rowsspan.value = 1;
			colsspan.value = 1;
			align.options[2].selected = true;
			valign.options[3].selected = true;
			width.value = 100;
			height.value = '';
			units1.options[1].selected = true;
			units2.options[1].selected = true;
			nowrap.checked = false;
			bgColor.style.backgroundColor = '';
			ckWidth.checked = false;
			ckHeight.checked = false;
			borderStyle.options[0].selected = true;
			borderStyle.disabled = true;
			borderWidth.value = 0;
			borderWidth.disabled = true;
			borderColor.style.backgroundColor = '';
		}
		return cellProperties;
	},
	_setCellProperties: function () {
		if (this._editableTableCell == null) return;
		var cellProp = this._getCellProperties(Typps.Editor.CommandType.Update);
		var sb = [];
		if (cellProp != null) {
			if (cellProp.rowsspan > 1)
				this._editableTableCell.setAttribute('rowspan', cellProp.rowsspan);
			else
				this._editableTableCell.removeAttribute('rowspan');
			if (cellProp.colsspan > 1)
				this._editableTableCell.setAttribute('colspan', cellProp.colsspan);
			else
				this._editableTableCell.removeAttribute('colspan');
			if (cellProp.align.toLowerCase() != 'left')
				this._editableTableCell.setAttribute('align', cellProp.align);
			else
				this._editableTableCell.removeAttribute('align');
			if (cellProp.valign.toLowerCase() != 'middle')
				this._editableTableCell.setAttribute('valign', cellProp.valign);
			else
				this._editableTableCell.removeAttribute('valign');
			if (cellProp.width > 0)
				Array.add(sb, 'width:' + cellProp.width + cellProp.widthUnit);
			if (cellProp.height != '')
				Array.add(sb, 'height:' + cellProp.height + cellProp.heightUnit);
			if (cellProp.bgColor != '')
				Array.add(sb, 'background-color:' + cellProp.bgColor);
			if (cellProp.borderWidth > 0) {
				Array.add(sb, 'border-width:' + cellProp.borderWidth + 'px');
				Array.add(sb, 'border-style:' + cellProp.borderStyle);
				if (cellProp.borderColor != '')
					Array.add(sb, 'border-color:' + cellProp.borderColor);
			}
			if (cellProp.nowrap)
				Array.add(sb, 'white-space:nowrap');
			if (sb.length > 0)
				this._editableTableCell.setAttribute('style', sb.join(';'));
			else
				this._editableTableCell.removeAttribute('style');
		}
	},
	_toggleDisability: function (id, ck, ddl, txtbox) {
		var status = (ck.checked) ? false : true;
		ddl.disabled = status;
		txtbox.disabled = status;
		if (status)
			txtbox.value = 0;
	},
	_btnTableBorderColorHandler: function (args) {
		var colorNode = $get(this._tableDesignerId + '_bordercolorpreview');
		var eventArgs = new Typps.EventArgs();
		eventArgs.set_commandName('tablebordercolor');
		eventArgs.set_commandArgument(colorNode);
		eventArgs.set_innerArgs(args);
		this._createColorPicker(eventArgs);
	},
	_btnTableBackgroundColorHandler: function (args) {
		var colorNode = $get(this._tableDesignerId + '_backgroundcolorpreview');
		var eventArgs = new Typps.EventArgs();
		eventArgs.set_commandName('tablebackgroundcolor');
		eventArgs.set_commandArgument(colorNode);
		eventArgs.set_innerArgs(args);
		this._createColorPicker(eventArgs);
	},
	_ckTableWidthHandler: function (event) {
		this._toggleDisability(this._tableDesignerId, event.target,
        $get(this._tableDesignerId + '_selunits1'),
        $get(this._tableDesignerId + '_txtwidth'));
	},
	_ckTableHeightHandler: function (event) {
		var id = this.get_id() + '_tabledesigner';
		this._toggleDisability(id, event.target, $get(id + '_selunits2'), $get(id + '_txtheight'));
	},
	_ckTableBorderHandler: function (event) {
		var borderColor = $get(this._tableDesignerId + '_bordercolorpreview');
		var borderStyle = $get(this._tableDesignerId + '_seltableborder');
		var borderWidth = $get(this._tableDesignerId + '_txtborder');
		var btnBorder = $get(this._tableDesignerId + '_btnbordercolor');
		var status = (event.target.checked) ? false : true;
		borderStyle.disabled = status;
		borderWidth.disabled = status;
		var visibility = status ? 'hidden' : 'visible';
		borderColor.style.visibility = visibility;
		btnBorder.style.visibility = visibility;
		borderWidth.value = status ? 0 : 1;
		if (status) {
			borderColor.style.backgroundColor = '';
			borderStyle.selectedIndex = 0;
		}
	},
	_ckTablePaddingHandler: function (event) {
		$get(this._tableDesignerId + '_txtpadding').disabled = (event.target.checked) ? false : true;
	},
	_ckTableSpacingHandler: function (event) {
		$get(this._tableDesignerId + '_txtspacing').disabled = (event.target.checked) ? false : true;
	},
	_displayFloatingToolBar: function () {
		var floatingContainer = $get(this.get_id() + '_floatingToolBar');
		if (floatingContainer.style.visibility != 'hidden') return;
		var distance = Typps.Utility.scrollDistance();
		if (this._isIE && Sys.Browser.version == 6) {
			floatingContainer.style.top = distance.y + 'px';
			floatingContainer.style.left = distance.x + 'px';
		}
		floatingContainer.style.display = '';
		floatingContainer.style.visibility = 'visible';
		var bounds = Typps.Utility.windowBounds();
		var barWidth = Typps.Utility.getScrollBarWidth();
		var x = bounds.ix;
		var html = document.getElementsByTagName('html')[0];
		if (html.scrollHeight > bounds.iy && !this._isIE)
			x -= barWidth;
		floatingContainer.style.width = x + 'px';
		var floatingToolBarCloseButton = $get(this.get_id() + '_floatingToolBarCloseButton');
		floatingToolBarCloseButton.parentNode.parentNode.style.width = '100%';
		if (this._floatingToolBarCloseButtonDelegate === null) {
			this._floatingToolBarCloseButtonDelegate = Function.createDelegate(this, this._floatingToolBarCloseButtonHandler);
			Sys.UI.DomEvent.addHandler(floatingToolBarCloseButton, 'click', this._floatingToolBarCloseButtonDelegate);
		}
		this._applyExplictToolBarItemWidth();
	},
	_floatingToolBarCloseButtonHandler: function (event) {
		this._floatingToolBarShow(false);
		var toolBarCollection = this.get_toolBarCollection();
		var id = this.get_id();
		for (var index in toolBarCollection) {
			var shader = $get(String.format('{0}_{1}_{2}', id, index, 'shade'));
			if (shader != null)
				shader.style.display = 'none';
		}
	},
	_floatingToolBarShow: function (status) {
		var id = this.get_id();
		var floatingContainer = $get(id + '_floatingToolBar');
		if (status)
			floatingContainer.style.visibility = 'visible';
		else
			floatingContainer.style.visibility = 'hidden';
	},
	_snapBackFloatingToolBarContainer: function () {
		var id = this.get_id();
		var floatingContainer = $get(id + '_floatingToolBar');
		if (floatingContainer == null) return;
		var bounds = Typps.Utility.windowBounds();
		var barWidth = Typps.Utility.getScrollBarWidth();
		var x = bounds.ix;
		var html = document.getElementsByTagName('html')[0];
		if (html.scrollHeight > bounds.iy && !this._isIE)
			x -= barWidth;
		floatingContainer.style.width = x + 'px';
		this._toolBarShaderShow(null);
	},
	_initializeDetachableToolBar: function () {
		var toolBarId = this._toolbarContainerId;
		if (!Typps.Utility.isNullOrEmpty(toolBarId) && !this._enableToolBarFloat) {
			var id = this.get_id();
			var toolbar = $get(id + '_toolbar');

			var detachableToolBarContainer = $get(this._toolbarContainerId);
			if (toolbar != null && detachableToolBarContainer != null) {
				detachableToolBarContainer.appendChild(toolbar.parentNode.removeChild(toolbar));
				toolbar.style.visibility = 'visible';
			}
		}
	},
	_applyExplictToolBarItemWidth: function () {
		//IE7 has an odd behavior when dealing with floats and no explict
		//width. It simply does not know when to adjust to the next line
		//so lets help it.
		var mode = this._mode;
		var enableToolBarFloat = this._enableToolBarFloat;
		var flag1 = (this._isIE && Sys.Browser.version < 8);
		if ((flag1 && !enableToolBarFloat) && mode == 1) {
			/*Old code below, refactor to use the new toolbar api which is faster and more robust?*/
			var id = this.get_id();
			var toolBarCollection = this.get_toolBarCollection();
			for (var index in toolBarCollection) {
				var width = 0;
				var container = $get(String.format('{0}_{1}', id, index));
				var buttons = container.getElementsByTagName('a');
				for (var num1 = 0; num1 < buttons.length; num1++)
					width += buttons[num1].offsetWidth;
				container.style.width = width + 'px';
			}
		}
	},
	_toggleAllHyperlinkClickHandler: function (operation) {
		var hyperlinks = this.iframe.getElementsByTagName('a');
		var target = null;
		for (var num1 = 0; num1 < hyperlinks.length; num1++) {
			var hyperlink = hyperlinks[num1];
			if (operation == 0) {
				target = hyperlink.getAttribute('target');
				if (target != undefined && target != null)
					hyperlink.setAttribute('target2', target);

				hyperlink.removeAttribute('target');
				hyperlink.setAttribute('target', '_blank');
			}
			else {
				target = hyperlink.getAttribute('target2');
				hyperlink.removeAttribute('target');
				if (target != undefined && target != null)
					hyperlink.setAttribute('target', target);
				hyperlink.removeAttribute('target2');
			}
		}
	},
	_previewMode: function (args) {
		this._toggleAllHyperlinkClickHandler(Typps.Perform.Add);
		if (Typps.Utility.isDesignMode(this.iframe))
			this._toggleCssClass(this.iframe.body, this._className + '-htmlelementlabels');
		this._warningsLog.style.display = 'none';
		this._nonEditableHtml.style.display = 'none';
		this._editorText.style.display = 'none';
		this.iframeElement.style.display = '';
		Typps.Utility.setDesignMode(this.iframe, false);
		this._currentTabView = Typps.Editor.TabView.Preview;
	},
	designViewMode: function (args) {
		this._toggleAllHyperlinkClickHandler(Typps.Perform.Remove);
		if (!Typps.Utility.isDesignMode(this.iframe))
			this._toggleCssClass(this.iframe.body, this._className + '-htmlelementlabels');
		if (this._autoPromptMultiFileUpload && this._hasLocalFilePath()) {
			this._multiFileActivation = Typps.Editor.Activation.Automatic;
			this._multiFileUploader();
			return;
		}
		if (this._isHtmlDirty && args != null)
			this._requestHtml(args, this._editorText.value);
		else
			this._setDesignViewMode(this.get_htmlText());
		this._isHtmlDirty = false;
	},
	_setDesignViewMode: function (htmlText) {
		htmlText = this._paragraphWrappedInnerHTML(htmlText);
		this._warningsLog.style.display = 'none';
		this._nonEditableHtml.style.display = 'none';
		this.iframeElement.style.display = '';
		if (this._editorText.style.display != 'none')
			this.set_htmlText(htmlText);
		this._editorText.style.display = 'none';
		Typps.Utility.setDesignMode(this.iframe, true);
	},
	_requestHtml: function (args, html) {
		var argument = Typps.Utility.getCommandArgument(args.get_commandName(), this.get_callbacks());
		var formKeyValuePair = { formdata: argument.commandArgument };
		formKeyValuePair[this._uniqueId + '$htmlview'] = html;
		formKeyValuePair['iscallback$htmlview$Typps'] = 'true';
		this._fireUpdatePanelTrigger(formKeyValuePair, argument.commandArgument, argument.message);
	},
	_htmlViewMode: function (args) {
		if (this._editorText.style.display != 'none')
			return;
		this._toggleAllHyperlinkClickHandler(Typps.Perform.Remove);
		this._isHtmlDirty = true;
		if (this._autoPromptMultiFileUpload && this._hasLocalFilePath()) {
			this._multiFileActivation = Typps.Editor.Activation.Automatic;
			this._multiFileUploader();
			return;
		}
		var htmlText = this._paragraphWrappedInnerHTML(this.get_htmlText());
		this._requestHtml(args, htmlText);
	},
	_htmlViewHilight: function (args) {
		if (this._nonEditableHtml.style.display != 'none')
			return;
		this._toggleAllHyperlinkClickHandler(Typps.Perform.Remove);
		var htmlText = this.get_htmlText();
		if (this._editorText.style.display != 'none')
			htmlText = this._editorText.value;
		htmlText = this._paragraphWrappedInnerHTML(htmlText);
		this._requestHtml(args, htmlText);
	},
	_warningLog: function (args) {
		if (this._editorText.style.display != 'none')
			this.set_htmlText(this._editorText.value);
		this._toggleAllHyperlinkClickHandler(Typps.Perform.Remove);
		this.iframeElement.style.display = 'none';
		this._editorText.style.display = 'none';
		this._nonEditableHtml.style.display = 'none';
		this._warningsLog.style.display = '';
		this._currentTabView = Typps.Editor.TabView.WarningLog;
	},

	_spellCheckerLangInitCallback: function (args) {
		var argument = Typps.Utility.getCommandArgument(args.get_commandName(), this.get_callbacks());
		var formKeyValuePair = { formdata: argument.commandArgument };
		if (this._dropDownListSpellChecker === null)
			this._fireUpdatePanelTrigger(formKeyValuePair, argument.commandArgument, argument.message);
		else
			this._dropDownListSpellChecker.show();
	},
	_classNamesListInitCallback: function (args) {
		var argument = Typps.Utility.getCommandArgument(args.get_commandName(), this.get_callbacks());
		var formKeyValuePair = { formdata: argument.commandArgument };
		if (this._cssClassNamesList === null)
			this._fireUpdatePanelTrigger(formKeyValuePair, argument.commandArgument, argument.message);
		else
			this._cssClassNamesList.show();
	},
	_saveInitCallback: function (command) {
		var argument = Typps.Utility.getCommandArgument(command, this.get_callbacks());
		var formKeyValuePair = { formdata: argument.commandArgument };
		this._editorText.value = this.get_htmlText();
		formKeyValuePair['iscallback$save$Typps'] = 'true';
		if (!this._postbackAllFormData)
			formKeyValuePair[this._editorText.name] = this._editorText.value;
		this._fireUpdatePanelTrigger(formKeyValuePair, argument.commandArgument, argument.message);
	},
	_wordCleanupInitCallback: function (command) {
		var argument = Typps.Utility.getCommandArgument(command, this.get_callbacks());
		var formKeyValuePair = { formdata: argument.commandArgument };
		if (this._wordCleanupWindow == null)
			this._fireUpdatePanelTrigger(formKeyValuePair, argument.commandArgument, argument.message);
		else
			this._wordCleanupWindow.show(true);
	},
	_codeHilighterInitCallback: function (command) {
		var argument = Typps.Utility.getCommandArgument(command, this.get_callbacks());
		var formKeyValuePair = { formdata: argument.commandArgument };
		if (this._codeHilighterWindow == null)
			this._fireUpdatePanelTrigger(formKeyValuePair, argument.commandArgument, argument.message);
		else
			this._codeHilighterWindow.show(true);
	},
	_imgDesignerInitCallback: function (command) {
		this._createImageDesigner();
	},
	_hyperLinkInitCallback: function (command) {
		var argument = Typps.Utility.getCommandArgument(command, this.get_callbacks());
		var formKeyValuePair = { formdata: argument.commandArgument };
		if (this._hyperlinkWindow == null) {
			this._fireUpdatePanelTrigger(formKeyValuePair, argument.commandArgument, argument.message);
		}
		else {
			this._editHyperlink();
			this._hyperlinkWindow.show(true);
		}
	},
	_fileBrowserInitCallback: function (command) {
		var argument = Typps.Utility.getCommandArgument(command, this.get_callbacks());
		var formKeyValuePair = { formdata: argument.commandArgument };
		if (this._fileBrowserWindow == null) {
			this._fireUpdatePanelTrigger(formKeyValuePair, argument.commandArgument, argument.message);
		}
		else {
			this._fileBrowserWindow.show(true);
		}
	},
	_tableDesignerInitCallback: function (command) {
		var argument = Typps.Utility.getCommandArgument(command, this.get_callbacks());
		var formKeyValuePair = { formdata: argument.commandArgument };
		if (this._tableDesignerWindow == null) {
			this._fireUpdatePanelTrigger(formKeyValuePair, argument.commandArgument, argument.message);
		}
		else {
			var commandType = (this._editableTableCell == null) ?
            Typps.Editor.CommandType.AddNew :
            Typps.Editor.CommandType.Edit;

			this._getTableProperties(commandType);
			this._tableDesignerWindow.show(true);
		}
	},
	_cellDesignerInitCallback: function (command) {
		var argument = Typps.Utility.getCommandArgument(command, this.get_callbacks());
		var formKeyValuePair = { formdata: argument.commandArgument };
		if (this._cellDesignerWindow == null) {
			this._fireUpdatePanelTrigger(formKeyValuePair, argument.commandArgument, argument.message);
		}
		else {
			this._getCellProperties(Typps.Editor.CommandType.Edit);
			this._cellDesignerWindow.show(true);
		}
	},

	_fireUpdatePanelTrigger: function (formKeyValuePair, commandName, message) {
		var eventArgs = new Typps.EventArgs();
		eventArgs.set_commandName(commandName);
		eventArgs.set_commandArgument(message);
		this._makeWebRequest(eventArgs, formKeyValuePair);
	},

	_formatBlock: function (args) {
		if (this._dropDownListFormatBlock === null) {
			var id = this.get_id() + '_ddlformatblock';
			var commandName = args.get_commandName();

			var formatBlockToolBarItem = this._toolBars.getToolBarItem(commandName);
			var title = formatBlockToolBarItem.get_title();
			var targetControl = formatBlockToolBarItem.get_element();

			var listItemClassName = this._className + '-dropdownformatblock';

			var list = [];
			var labels = this.get_formatBlockLabel();
			for (var num1 = 0; num1 < 8; num1++) {
				var el = null;
				var name = null;
				switch (num1) {
					case 0:
						name = labels.p + ' (p)';
						Array.add(list, { text: name, value: '<p>', toolTip: name, tagName: null });
						break;
					case 7:
						name = labels.pre + ' (pre)';
						Array.add(list, { text: name, value: '<pre>', toolTip: name, tagName: null });
						break;
					default:
						name = labels.h + ' (h' + num1 + ')';
						Array.add(list, { text: name, value: '<h' + num1 + '>', toolTip: name, tagName: 'h' + num1, styles: [{ key: 'padding', value: '0px' }, { key: 'margin', value: '0px'}] });
				}
			}

			var options = this._createDropDownListOptions(listItemClassName, title, commandName, targetControl, list, null, null, true, null);
			this._dropDownListFormatBlock = this._createDropDownList(id, options);
			this._createDropDownListDelegate(this._dropDownListFormatBlock);
		}
		this._dropDownListFormatBlock.show();
	},
	_setFontName: function (args) {
		if (this._dropDownListFontName === null) {
			var id = this.get_id() + '_ddlfontname';
			var commandName = args.get_commandName();

			var fontNameToolBarItem = this._toolBars.getToolBarItem(commandName);
			var title = fontNameToolBarItem.get_title();
			var targetControl = fontNameToolBarItem.get_element();

			var listItemClassName = this._className + '-dropdownfontname';
			var list = [];
			for (var index in this._fontNames) {
				var fontName = this._fontNames[index];
				Array.add(list, { text: fontName, value: fontName, toolTip: fontName, styles: [{ key: 'fontFamily', value: fontName}] });
			}
			var options = this._createDropDownListOptions(listItemClassName, title, commandName, targetControl, list, null, null, true, null);
			this._dropDownListFontName = this._createDropDownList(id, options);
			this._createDropDownListDelegate(this._dropDownListFontName);
		}
		this._dropDownListFontName.show();
	},
	_setFontSize: function (args) {
		if (this._dropDownListFontSize === null) {
			var id = this.get_id() + '_ddlfontsize';
			var commandName = args.get_commandName();

			var fontSizeToolBarItem = this._toolBars.getToolBarItem(commandName);
			var title = fontSizeToolBarItem.get_title();
			var targetControl = fontSizeToolBarItem.get_element();

			var listItemClassName = this._className + '-dropdownfontsize';

			var list = [];

			var text = 'abcdefg';
			var len = 8;
			if (this._isWebKit) {
				/*<span class="Apple-style-span" style="font-size: -webkit-xxx-large">Hello</span> is produced when font size is 7. too bad, so for webkit size 6 is max.*/
				text = text.substring(0, 6);
				len--;
			}
			for (var num1 = 1; num1 < len; num1++)
				Array.add(list, { text: text, value: num1, toolTip: num1, attributes: [{ key: 'size', value: num1}], tagName: 'font' });
			var options = this._createDropDownListOptions(listItemClassName, title, commandName, targetControl, list, null, null, true, null);
			this._dropDownListFontSize = this._createDropDownList(id, options);
			this._createDropDownListDelegate(this._dropDownListFontSize);
		}
		this._dropDownListFontSize.show();
	},
	_createDropDownListOptions: function (listItemClassName, title, commandName, targetControl, list, menuList, iframeContainer, isToolBar, selectedStyle) {
		if (selectedStyle == null)
			selectedStyle = this._className + '-dropdownstyle-selected';
		return {
			dropDownClassName: this._className + '-dropdownstyle', /*The table that creates the layout for the dropdown*/
			listItemClassName: listItemClassName, /*The ul list holding each listitem displayed in the dropdownlist*/
			selectedItemClassName: selectedStyle,
			menuItemClassName: this._className + '-menulist', /*The ul list holding each command menu item*/
			headerClassName: this._className + '-dropdownheaderstyle',
			closeButtonClassName: 'tristateclosebutton16x48',
			commandName: commandName,
			title: title,
			targetControl: targetControl,
			list: list,
			menuList: menuList, /*a list of command buttons positioned under the dropdownlist*/
			enableToolBarFloat: this._enableToolBarFloat,
			iframeContainer: iframeContainer,
			isToolBar: isToolBar,
			enableEffects: this._enableDropDownListEffects,
			effectDuration: this._dropDownListEffectDuration
		};
	},
	_createDropDownList: function (id, options) {
		var dropDownList = $find(id);
		if (dropDownList != null) return dropDownList;

		var elem = document.createElement('div');
		elem.id = id;
		this._element.parentNode.insertBefore(elem, this._element);
		return $create(Typps.DropDownList, options, null, null, elem);
	},
	_createDropDownListDelegate: function (dropDownList) {
		if (this._ddlSelectDelegate === null)
			this._ddlSelectDelegate = Function.createDelegate(this, this._ddlSelectHandler);
		dropDownList.add_listItemSelected(this._ddlSelectDelegate);

		if (this._ddlCloseDelegate === null)
			this._ddlCloseDelegate = Function.createDelegate(this, this._ddlCloseHandler);
		dropDownList.add_close(this._ddlCloseDelegate);
	},
	_quote: function () {
		var blockquote = this.iframe.createElement('blockquote');
		this.rangeComponent.insertBlockLevelElement(blockquote, this._lastRange, true);
		this._ensureLastParagraph();
	},
	_getAncestorByTagName: function (node, tagName) {
		if (node == null) return null;
		while (node) {
			var nodeName = node.nodeName.toLowerCase();
			if (nodeName == 'body') return null;
			else if (nodeName == tagName) return node;
			node = node.parentNode;
		}
		return null;
	},
	_deleteRow: function (table, rowIndex, cellIndex) {
		var rowCount = table.rows.length;
		if (rowCount > 1) {
			table.deleteRow(rowIndex);

			var row = table.rows[0];
			if (row != null) {
				var col = row.cells[cellIndex];
				this.rangeComponent.selectAll([col]);
			}
		}
		else {
			table.parentNode.removeChild(table);
		}
	},
	_editTableElement: function (command) {
		var selectedItem = this.rangeComponent.getAllNodesInRange(this._lastRange);
		var nodes = selectedItem.get_nodes();
		var cursorNode = selectedItem.get_cursorNode();

		if (cursorNode == null) return;

		var table = null;
		if (command == 'deletetable') {
			table = this._getAncestorByTagName(cursorNode, 'table');
			if (table != null) {
				table.parentNode.removeChild(table);
			}
			return;
		}

		var td = this._getAncestorByTagName(cursorNode, 'td');
		if (td == null) return;

		var tr = td.parentNode;
		var cellIndex = td.cellIndex;
		var rowIndex = tr.rowIndex;
		table = this._getAncestorByTagName(tr, 'table');
		if (table == null) return;

		var rowCount = table.rows.length;
		switch (command) {
			case 'addrowafter': //add row after
				rowIndex++;
				this._insertRow(table.insertRow(rowIndex), tr);
				break;
			case 'addrowbefore': //add row before
				rowIndex = rowIndex--;
				this._insertRow(table.insertRow(rowIndex), tr);
				break;
			case 'addcolumnafter': //add column after
				this._cellAddRemove(table, td, cellIndex, false, true);
				break;
			case 'addcolumnbefore': //add column before
				this._cellAddRemove(table, td, cellIndex, true, true);
				break;
			case 'deleterow': //delete row
				this._deleteRow(table, rowIndex, cellIndex);
				break;
			case 'deletecolumn': //delete column
				var columnCount = table.rows[rowIndex].cells.length;
				if (columnCount > 1)
					this._cellAddRemove(table, td, cellIndex, true, false);
				else
					this._deleteRow(table, rowIndex, cellIndex);
				break;
		}
	},
	_insertRow: function (row, tr) {
		for (var num1 = 0; num1 < tr.childNodes.length; num1++) {
			var col = tr.childNodes[num1];
			if (col.nodeName.toLowerCase() == 'td') {
				var clone = col.cloneNode(false);
				row.appendChild(clone);
				if (!this._isIE)
					clone.appendChild(document.createElement('br'));
			}
		}
	},

	_cellAddRemove: function (table, td, index, insertBefore, addCell) {
		var len1 = table.tBodies.length;
		for (var num1 = 0; num1 < len1; num1++) {
			var tBody = table.tBodies[num1];
			var refRow = td.parentNode;
			var len2 = tBody.childNodes.length;
			for (var num2 = 0; num2 < len2; num2++) {
				var row = tBody.childNodes[num2];
				if (row.nodeName.toLowerCase() == 'tr') {
					if (row.cells[index] != null) {
						if (addCell) {
							var clone = row.cells[index].cloneNode(false);
							if (!this._isIE)
								clone.appendChild(document.createElement('br'));
							if (insertBefore)
								row.insertBefore(clone, row.cells[index]);
							else {
								if (row.cells.length > (index + 1))
									row.insertBefore(clone, row.cells[index + 1]);
								else
									row.appendChild(clone);
							}
						}
						else {
							row.deleteCell(index);
						}
					}
				}
			}
		}
		if (refRow.cells.length > 0) {
			var col = refRow.cells[index];
			this.rangeComponent.selectAll([col]);
		}
	},
	_executeCommand: function (args) {
		var val = args.get_commandArgument();
		var commandName = args.get_commandName();
		this._disposeSuggestionDropDownList(null);
		this._disposeSpellCheckerElements();
		var flag = false;
		var h = null;
		var eventArgs = null;
		switch (commandName) {
			case 'print':
				break;
			case 'csslist':
				this._classNamesListInitCallback(args);
				return;
			case 'save':
				eventArgs = new Typps.EventArgs();
				eventArgs.set_innerArgs(args);
				eventArgs.set_commandName(commandName);
				var length = this._maxLengthReached();
				if (length != -1) {
					eventArgs.set_commandArgument(length);
					h = this.get_events().getHandler('maxlengthreached');
					if (h) h(this, eventArgs);
				} else {
					var htmlText = this.get_htmlText();
					eventArgs.set_commandArgument(htmlText);
					h = this.get_events().getHandler('saving');
					if (h) h(this, eventArgs);
					this._saveInitCallback(commandName);
				}
				return;
			case 'wordcleanup':
				this._wordCleanupInitCallback(commandName);
				return;
			case 'codehilighter':
				this._codeHilighterInitCallback(commandName);
				return;
			case 'createlink':
				this._hyperLinkInitCallback(commandName);
				return;
			case 'inserttable':
				this._tableDesignerInitCallback(commandName);
				return;
			case 'cellsdesigner':
				this._cellDesignerInitCallback(commandName);
				return;
			case 'deletetable': //delete table
				this._editTableElement(commandName);
				return;
			case 'addrowafter': //add row after
				this._editTableElement(commandName);
				return;
			case 'addrowbefore': //add row before
				this._editTableElement(commandName);
				return;
			case 'addcolumnafter': // add column after
				this._editTableElement(commandName);
				return;
			case 'addcolumnbefore': // add column before
				this._editTableElement(commandName);
				return;
			case 'deleterow': // delete row
				this._editTableElement(commandName);
				return;
			case 'deletecolumn': // delete column
				this._editTableElement(commandName);
				return;
			case 'insertimage':
				this._imgDesignerInitCallback(commandName);
				return;
			case 'spell':
				this._spellCheckerLangInitCallback(args);
				return;
			case 'designview':
				this.designViewMode(args);
				return;
			case 'htmlview':
				this._htmlViewMode(args);
				return;
			case 'preview':
				this._previewMode(args);
				return;
			case 'htmlviewhilight':
				this._htmlViewHilight(args);
				return;
			case 'warninglog':
				this._warningLog(args);
				return;
			case 'hilitecolor':
				if (this._isIE)
					args.set_commandName('backcolor');
				this._createColorPicker(args);
				return;
			case 'backcolor':
				this._createColorPicker(args);
				return;
			case 'forecolor':
				this._createColorPicker(args);
				return;
			case 'fontsize':
				this._setFontSize(args);
				return;
			case 'fontname':
				this._setFontName(args);
				return;
			case 'formatblock':
				this._formatBlock(args);
				return;
			case 'delete':
				break;
			case 'quote':
				this._quote();
				return;
			case 'multifileuploader':
				this._multiFileActivation = Typps.Editor.Activation.Manual;
				break;
		}
		this.documentExecCommand(commandName, val);
		if (commandName == 'removeformat')
			this._removeFormat();
		if (commandName == 'delete')
			this._ensureLastParagraph();
	},
	_removeFormat: function () {
		if (!this._isIE) return;
		var parentElem = this._lastRange.parentElement();
		if (parentElem == null) return;

		var nodeName = parentElem.nodeName.toLowerCase();
		var text = this._lastRange.text;
		var htmlText = this._lastRange.htmlText;
		var flag1 = false;
		var temp = parentElem;
		var bookmark = this.rangeComponent._bookmark;

		if (nodeName == 'body' && htmlText != '') {
			temp = document.createElement('div');
			Typps.Utility.getAdjacentHTML(htmlText, temp);
			flag1 = true;
		}
		for (var num1 = 0; num1 < temp.childNodes.length; num1++) {
			var elem = temp.childNodes[num1];
			if (elem.nodeType == 1)
				this._removeStyleFormatting(elem);
		}
		if (flag1) {
			/*
			pasteHTML pastes our changes in inner content of our selection.
			but we'd like to replace outerHTML of the selection, so let's 
			do something fancy to meet this requirement.
			*/
			if (this._lastRange.select) {
				this._lastRange.select();
			}
			this._lastRange.pasteHTML('<div id="typpscarat1"></div>');
			carat = $get('typpscarat1', this.iframe);
			replacementNode = carat.parentNode;
			nodeName = replacementNode.nodeName.toLowerCase();
			try {
				if (nodeName != 'body')
					replacementNode.insertAdjacentHTML('beforeBegin', temp.innerHTML);
				else
					replacementNode.innerHTML = temp.innerHTML;
				this._lastRange.collapse();
				this._lastRange.moveToElementText(replacementNode);
			} catch (exception) { /*htmlfile: invalid source html for this operation error caused by possible invalid html in temp.innerHTML (fixed)*/ }
			if (nodeName != 'body')
				replacementNode.parentNode.removeChild(replacementNode);
		}
		else {
			this._removeStyleFormatting(parentElem);
			if (bookmark != null) {
				this._lastRange.collapse();
				this._lastRange.moveToBookmark(bookmark);
			}
		}
		if (this._lastRange.select) {
			this._lastRange.select();
		}
	},
	_removeStyleFormatting: function (elem) {
		if (elem.nodeType == 1) {
			var attributes = ['class'];
			for (var index1 in attributes) {
				var attr = attributes[index1];
				elem.removeAttribute(attr);
			}
			var styleAttributes = ['color', 'textAlign', 'backgroundColor', 'fontSize', 'fontFamily']; //add more in future
			var nodeName = elem.nodeName.toLowerCase();
			if (nodeName == 'br') return;
			for (var index2 in styleAttributes) {
				var value = styleAttributes[index2];
				if (elem.style[value] != '') {
					elem.style[value] = '';
				}
			}
			if (nodeName == 'span' && elem.attributes.length == 0) {
				for (var num1 = 0; num1 < elem.childNodes.length; num1++) {
					var node = elem.childNodes[num1];
					if (node.nodeType == 3)
						elem.insertAdjacentHTML('beforeBegin', node.data);
					else
						elem.insertAdjacentHTML('beforeBegin', node.outerHTML);
				}
				elem.parentNode.removeChild(elem);
			}
		}
		for (var num1 = 0; num1 < elem.childNodes.length; num1++)
			this._removeStyleFormatting(elem.childNodes[num1]);
	},
	documentExecCommand: function (command, value) {
		var success = false;
		var isJustifyCommand = this._justify(command);
		var body = this.iframe.body;
		switch (command) {
			case 'selectall':
				break;
			default:
				if (body != null && this._isIE)
					body.focus();
				break;
		}
		try {
			if (this._isFF && !isJustifyCommand)
				this.iframe.execCommand('styleWithCSS', null, false);
			else if (this._isFF)
				this.iframe.execCommand('styleWithCSS', null, true);
			success = this.iframe.execCommand(command, false, value);
		}
		catch (exception) { }
		if ((this._isIE || this._isOpera) && isJustifyCommand)
			this._setJustification(command);
	},
	_normalizeBlockQuotes: function () {
		/*when switching from designview/htmlview, we format the html.
		the whitepsace causes outdent command to malfunction.this fixes it*/
		var blockQuotes = this.iframe.body.getElementsByTagName('blockquote');
		var len = blockQuotes.length;
		for (var num1 = 0; num1 < len; num1++) {
			var quote = blockQuotes[num1];
			this._removeWhiteSpace(quote.parentNode);
		}
	},
	_removeWhiteSpace: function (node) {
		for (var i = 0; i < node.childNodes.length; i++) {
			var child = node.childNodes[i];
			if (child.nodeType == 3 && !/\S/.test(child.nodeValue)) {
				node.removeChild(child);
				i--;
			}
			if (child.nodeType == 1) {
				this._removeWhiteSpace(child);
			}
		}
		return node;
	},
	_justify: function (commandName) {
		return Array.contains(['justifyleft', 'justifycenter', 'justifyright', 'justifyfull'], commandName);
	},
	_setJustification: function (command) {
		if (!(this._isIE || this._isOpera)) return;
		var elements = this.iframe.body.getElementsByTagName('*');
		for (var num1 = 0; num1 < elements.length; num1++) {
			var elem = elements[num1];
			if (elem.nodeType == 1)
				this._convertAlignAttributeToCss(elem, command);
		}
	},
	_convertAlignAttributeToCss: function (elem, command) {
		var nodeName = elem.nodeName.toLowerCase();
		var justifyList = [{ key: 'justifyleft', value: 'left' }, { key: 'justifycenter', value: 'center' },
                { key: 'justifyright', value: 'right' }, { key: 'justifyfull', value: 'justify'}];

		switch (nodeName) {
			case 'td':
			case 'col':
			case 'colgroup':
			case 'tbody':
				return;
				break;
		}
		var att = elem.getAttribute('align');
		if (att != undefined) {
			for (var index in justifyList) {
				var pair = justifyList[index];
				if (pair.key == command && att == pair.value) {
					elem.removeAttribute('align');
					elem.style.textAlign = pair.value;
					break;
				}
			}
		}
	},
	_toolBarShaderShow: function (status) {
		var toolBarCollection = this.get_toolBarCollection();
		var id = this.get_id();
		for (var index in toolBarCollection) {
			var toolBarSetElement = $get(id + '_' + index);
			this._toolBarShader(toolBarSetElement, status);
		}
		if (status) {
			/*IE7 buggy again :| --The button just mysteriously dissappears, so
			lets fix that introducing a delay*/
			var floatingToolBarCloseButton = $get(id + '_floatingToolBarCloseButton');
			if (floatingToolBarCloseButton != null) {
				floatingToolBarCloseButton.style.display = 'none';
				window.setTimeout(function () { floatingToolBarCloseButton.style.display = ''; }, 1);
			}
		}
	},
	_toolBarShader: function (toolBar, status) {
		var id = toolBar.id + '_shade';
		var shadeElement = $get(id);
		if (this._enableToolBarFloat) {
			var floatingContainer = $get(this.get_id() + '_floatingToolBar');
			if (floatingContainer.style.visibility == 'hidden') return;
		}
		var p = Typps.Utility.getParentOffset(toolBar);
		var distance = Typps.Utility.scrollDistance();
		var isIE6 = (this._isIE && Sys.Browser.version == 6);
		if (shadeElement == null) {
			shadeElement = document.createElement('div');
			shadeElement.id = id;
			var style = shadeElement.style;
			style.height = toolBar.offsetHeight + 'px';
			style.width = toolBar.offsetWidth + 'px';
			style.backgroundColor = this._toolBarShadeColor;
			Typps.Utility.setTransparency(shadeElement, 50);
			style.display = 'none';
			toolBar.appendChild(shadeElement);
			style.position = 'absolute';
		}

		var left = p.x;
		var top = p.y;
		if (isIE6 && this._enableToolBarFloat) {
			p.x -= distance.x;
			p.y -= distance.y;
		}
		shadeElement.style.left = p.x + 'px';
		shadeElement.style.top = p.y + 'px';

		if (status != null)
			shadeElement.style.display = (status) ? '' : 'none';
	},
	_ddlSelectHandler: function (sender, args) {
		var h = this.get_events().getHandler('ddlSelect');
		if (h) h(this, args);
		var commandName = args.get_commandName();
		var value = args.get_selectedValue();
		if (this._isIE) {
			var text = this._lastRange.text;
			if (text != '') {
				this._lastRange.collapse();
				this._lastRange.findText(text);
			}
			if (commandName == 'fontsize') {
				var parentNode = this._lastRange.parentElement();
				if (parentNode.nodeName.toLowerCase() == 'span' && parentNode.style.fontSize != '') {
					parentNode.style.fontSize = this._getCssSize(value);
					this._maintainSelection(parentNode);
					return;
				}
			}
		}

		this.documentExecCommand(commandName, value);
		if (commandName == 'fontsize')
			this._fixDeprecatedFontElements(commandName);
	},
	_maxLengthReached: function () {
		var maxLength = this._maxLength;
		if (maxLength <= 0) return -1;
		var innerText = new Sys.StringBuilder();
		var node = this.iframe.body.firstChild;
		while (node) {
			switch (node.nodeType) {
				case 1/*ELEMENT_NODE*/:
					if (node.textContent)
						innerText.append(node.textContent);
					else if (node.innerText)
						innerText.append(node.innerText);
					break;
				case 3/*TEXT_NODE*/:
					innerText.append(node.data);
					break;
			}
			node = node.nextSibling;
		}
		var length = innerText.toString().length
		if (length > maxLength)
			return length;
		return -1;
	},
	_ddlCloseHandler: function (args) {
		var h = this.get_events().getHandler('ddlclose');
		if (h) h(this, args);
	},
	_toggleCssClass: function (elem, className) {
		Typps.Utility.addRemoveClassName(elem, className, Typps.Perform.Toggle);
	},
	_addCssClass: function (elem, className) {
		Typps.Utility.addRemoveClassName(elem, className, Typps.Perform.Add);
	},
	_removeCssClass: function (elem, className) {
		Typps.Utility.addRemoveClassName(elem, className, Typps.Perform.Remove);
	}
}

Typps.Editor.registerClass('Typps.Editor', Sys.UI.Control);

Typps.Editor.IconType = function () { };
Typps.Editor.IconType.prototype =
{
    ImageSprites: 0,
    Icons: 1
}
Typps.Editor.IconType.registerEnum('Typps.Editor.IconType');
Typps.Editor.Dir = function () { };
Typps.Editor.Dir.prototype =
{
    LTR: 0,
    RTL: 1
}
Typps.Editor.Dir.registerEnum('Typps.Editor.Dir');
Typps.Editor.ToolBarButton = function () { };
Typps.Editor.ToolBarButton.prototype =
{
    Get: 0,
    ResetAll: 1
}
Typps.Editor.ToolBarButton.registerEnum('Typps.Editor.ToolBarButton');
Typps.Editor.CommandType = function () { };
Typps.Editor.CommandType.prototype =
{
    Edit: 0,
    AddNew: 1,
    Update: 2,
    Delete: 3,
    Cancel: 4
}
Typps.Editor.CommandType.registerEnum('Typps.Editor.CommandType');
Typps.Editor.TabView = function () { };
Typps.Editor.TabView.prototype =
{
    DesignView: 0,
    HtmlView: 1,
    HtmlViewColored: 2,
    Preview: 3,
    WarningLog: 4
}
Typps.Editor.TabView.registerEnum('Typps.Editor.TabView');
Typps.Editor.Activation = function () { };
Typps.Editor.Activation.prototype =
{
    Automatic: 0,
    Manual: 1
}
Typps.Editor.Activation.registerEnum('Typps.Editor.Activation');
Typps.Editor.ButtonType = function () { };
Typps.Editor.ButtonType.prototype =
{
    ToolBar: 0,
    Tab: 1
}
Typps.Editor.ButtonType.registerEnum('Typps.Editor.ButtonType');
// Since this script is not loaded by System.Web.Handlers.ScriptResourceHandler
// invoke Sys.Application.notifyScriptLoaded to notify ScriptManager 
// that this is the end of the script.
if (typeof (Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();
